I am using Visual Studio 2017 C++. When I use printf with a specification such as %llx or %llu everything works as expected. If I use the same format spec, %llu or %llx, with wsprintf, I get junk in the buffer instead of the result I had gotten with printf.
My question is: is there a way to get wsprintf to give the result that should be obtained when using %llx and/or %llu ?
Below is a very simple console program that demonstrates the different behavior of printf and wsprintf.
#include "stdafx.h"
#include <Windows.h>
#include <inttypes.h>
int main()
{
DWORD64 OffsetHWM = 0x7123456789012345;
WCHAR BufferBytes[256] = { 0 }; // initialized - no junk in there
// the wprintf below works as expected
wprintf(L"from wprintf : %8llX\n", OffsetHWM);
// this call to wsprintf isn't filling the buffer with the expected value
wsprintf(BufferBytes, L"%8llX\n", OffsetHWM);
wprintf(L"from wsprintf: %s\n", BufferBytes); // prints junk
wprintf(L"\n"); // just for neatness
wsprintf(BufferBytes, L"%8" PRIx64 "\n", OffsetHWM);
wprintf(L"from wsprintf: %s\n", BufferBytes);
// this truncates (as expected) the value of OffsetHWM - not useful
wsprintf(BufferBytes, L"%8lx\n", OffsetHWM);
wprintf(L"from wsprintf: %s\n", BufferBytes);
return 0;
}
wprintf() should not be used any more, it is a Windows specific function which calls either wsprintfA() or wsprintfW() to do the actual work, both of which have the following note on their Windows Dev Centre Documentation site (https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-wsprintfa):
Note Do not use. Consider using one of the following functions instead: StringCbPrintf, StringCbPrintfEx, StringCchPrintf, or StringCchPrintfEx. See Security Considerations.
Related
I'm writing a program that must take user input to assign values to parts of a structure. I need to create a pointer to the structure that I will pass through as a one and only parameter for a function that will print each part of the structure individually. I also must malloc memory for the structure. As it is now, the program compiles and runs through main and asks the user for inputs. A segmentation fault occurs after the last user input is collected and when I'm assuming the call to the printContents function is run. Any help would be appreciated!
#include <stdio.h>
#include <stdlib.h>
struct info
{
char name[100], type;
int size;
long int stamp;
};
void printContents(struct info *iptr);
int main(void)
{
struct info *ptr=malloc(sizeof(struct info));
printf("Enter the type: \n");
scanf("%c", &(*ptr).type);
printf("Enter the filename: \n");
scanf("%s", (*ptr).name);
printf("Enter the access time: \n");
scanf("%d", &(*ptr).stamp);
printf("Enter the size: \n");
scanf("%d", &(*ptr).size);
printf("%c", (*ptr).type);
printContents(ptr);
}
void printContents(struct info *iptr)
{
printf("Filename %s Size %d Type[%s] Accessed # %d \n", (*iptr).name, (*iptr).size, (*iptr).type, (*iptr).stamp);
}
Check the operator precedence. Is this &(*ptr).type the thing you're trying to do? Maybe &((*ptr).type) ?
ptr->member is like access to structure variable right? Also same for scanf() usr &ptr->member to get value. For char input use only ptr->charmember .
First let's do it the hard way. We'll assume that the code is already written, the compiler tells us nothing useful, and we don't have a debugger. First we put in some diagnostic output statements, and we discover that the crash happens in printContents:
printf("testing four\n"); /* we see this, so the program gets this far */
printf("Filename %s Size %d Type[%s] Accessed # %d \n", (*iptr).name, (*iptr).size, (*iptr).type, (*iptr).stamp);
printf("testing five\n"); /* the program crashes before this */
If we still can't see the bug, we narrow the problem down by preparing a minimal compete example. (This is a very valuable skill.) We compile and run the code over and over, commenting things out. When we comment something out and the code still segfaults, we remove it entirely; but if commenting it out makes the problem go away, we put it back in. Eventually we get down to a minimal case:
#include <stdio.h>
int main(void)
{
char type;
type = 'a';
printf("Type[%s]\n", type);
}
Now it should be obvious: when we printf("%s", x) something, printf expects x to be a string. That is, x should be a pointer to (i.e. the address of) the first element of a character array which ends with a null character. Instead we've given it a character (in this case 'a'), which it interprets as a number (in this case 97), and it tries to go to that address in memory and start reading; we're lucky to get nothing worse than a segfault. The fix is easy: decide whether type should be a char or a char[], if it's char then change the printf statement to "%c", if it's char[] then change its declaration.
Now an easy way. If we're using a good compiler like gcc, it will warn us that we're doing something fishy:
gcc foo.c -o foo
foo.c:35: warning: format ‘%s’ expects type ‘char *’, but argument 4 has type ‘int’
In future, there's a way you can save yourself all this trouble. Instead of writing a lot of code, getting a mysterious bug and backtracking, you can write in small increments. If you had added one term to that printf statement at a time, you would have seen exactly when the bug appeared, and which term was to blame.
Remember: start small and simple, add complexity a little at a time, test at every step, and never add to code that doesn't work.
When I try to read a line from standard input and split it into words, after removing the /n character, I get a core dumped error. Could anyone explain me the reason? What is the correct way to do this?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE_LEN 50
#define MAX_PARTS 50
int main ()
{
char* token;
char *str;
char* arr[MAX_PARTS];
int i,j;
printf("Write a line: \n $:");
fgets(str, LINE_LEN, stdin);
str = strncpy(str, str, strlen(str)-1);
fflush(stdin);
i=0;
token = strtok(str, " ");
while( token != NULL )
{
arr[i] = token;
printf("%s",arr[i]);
i++;
token = strtok(NULL," ");
}
return 0;
}
You are printing the NULL pointer on your last pass through the while() loop. You probably need to reverse the printf() and strtok() calls like this:
while( token != NULL )
{
arr[i] = token;
printf("%s",arr[i]); # Must come first to avoid printing a NULL on final loop
i++;
token = strtok(NULL," ");
}
You are reading into unallocated memory.
char *str;
This declares a pointer str, which is pointing nowhere. (In fact, it points to a random location, but "nowhere" stops the guys who try to second-guess undefined behaviour.)
fgets(str, LINE_LEN, stdin);
This writes to the location str is pointing at, which is nowhere (see above). This is undefined behaviour. If your program happens to survive this (instead of SEGFAULTing right there), you cannot rely on it behaving in any sane manner from this point on.
While we're at it:
fflush(stdin);
Note that the C standard does not define the behaviour of fflush() when called on input streams, i.e. while this is well-defined under Linux (which does define this behaviour), this is a non-standard, non-portable construct that could well crash on other platforms.
I have a very strange problem with a sketch which performs differently if compiled and uploaded to Arduino from Windows XP Home sp3 or Elementary OS Luna (a distro of Ubuntu Linux).
This sketch, between other things, reads a byte from a serial connection (bluetooth) and write it back to serial monitor.
This is what I get if I compile the sketch from WinXP: I sent over BT connection strings from "1" to "7" one time each. The ASCII code of these strings are reduced of 48 to transform string in byte. The result is correct, also functions in pointer array are correctly called.
and here is what I get from Linux. I sent 4 times each string from "1" to "7" to see that result has nothing to do with what I need to get and also is not consistent with the same input data: for example when I send string "2" I get 104 106 106 104..... and same byte 106 is written with different Strings coming from BT.
Also the functions are not called so it means that is not a Serial.print issue.
I'm sure it is a compiling issue because once the sketch is uploaded in Arduino it performs in the same way (correct or not) if I use serial monitor in WinXP or Linux.
Here's the sketch
#include "Arduino.h"
#include <SoftwareSerial.h>
#include <Streaming.h>
#define nrOfCommands 10
typedef void (* CmdFuncPtr) (); // this is a typedef to command functions
//the following declares an arry of 10 function pointers of type DigitFuncPtr
CmdFuncPtr setOfCmds[nrOfCommands] = {
noOp,
leftWindowDown,
leftWindowUp,
bootOpen,
cabinLightOn,
cabinLightOff,
lockOn,
lockOff,
canStart,
canStop
};
#define cmdLeftWindowDown 1
#define cmdLeftWindowUp 2
#define cmdBootOpen 3
#define cmdCabinLightOn 4
#define cmdCabinLightOff 5
#define cmdLockOn 6
#define cmdLockOff 7
#define cmdCanStart 8
#define cmdCanStop 9
#define buttonPin 4 // the number of the pushbutton pin
#define bluetoothTx 2
#define bluetoothRx 3
int buttonState = 0; // variable for reading the pushbutton status
int androidSwitch=0;
byte incomingByte; // incoming data
byte msg[12];
byte msgLen=0;
byte msgIdMsb=0;
byte msgIdLsb=0;
//const byte cmdLeftWindowDown;
SoftwareSerial bluetooth(bluetoothTx,bluetoothRx);
void setup()
{
//Setup usb serial connection to computer
Serial.begin(115200);
//Setup Bluetooth serial connection to android
bluetooth.begin(115200);
//bluetooth.print("$$$");
randomSeed(analogRead(10));
delay(100);
//bluetooth.println("U,9600,E");
//bluetooth.begin(9600);
//time=0;
}
void loop() {
msgIdLsb=random(1,255);
msgIdMsb=random(0,5);
msg[0]=msgIdMsb;
msg[1]=msgIdLsb;
msgLen=random(9);
msg[2]=msgLen;
for (int x=3;x<msgLen+3;x++) {
msg[x]=random(255);
}
for (int x=3+msgLen;x<11;x++) {
msg[x]=0;
}
msg[11]='\n';
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
if ((buttonState == HIGH)||(androidSwitch==HIGH)) {
for (int x=0;x<12;x++) {
Serial<<msg[x]<<" ";
bluetooth.write(uint8_t(msg[x]));
}
Serial<<endl;
}
//Read from bluetooth and write to usb serial
if(bluetooth.available())
{
incomingByte = bluetooth.read()-48;
Serial<<incomingByte<<endl;
if (incomingByte<nrOfCommands)
setOfCmds[incomingByte]();
}
delay(10);
}
void noOp(void)
{
Serial<<"noOp"<<endl;
};
void leftWindowDown(void)
{
Serial<<"leftWindowDown"<<endl;
};
void leftWindowUp(void)
{
Serial<<"leftWindowUp"<<endl;
};
void bootOpen(void)
{
Serial<<"bootOpen"<<endl;
};
void cabinLightOn(void)
{
Serial<<"cabinLightOn"<<endl;
};
void cabinLightOff(void)
{
Serial<<"cabinLightOff"<<endl;
};
void lockOn(void)
{
Serial<<"lockOn"<<endl;
};
void lockOff(void)
{
Serial<<"lockOff"<<endl;
};
void canStart(void)
{
androidSwitch=HIGH;
};
void canStop(void)
{
androidSwitch=LOW;
};
Any help would be very helpful.
Thanks in advance.
I suppose you are using the arduino ide; if not, some of the following might not apply.
First, find out the location of the build directory the ide is using when it compiles and links the code. [One way to find out is to temporarily turn on Verbose output during compilation. (Click File, Preferences, "Show verbose output during compilation".) Click the Verify button to compile the code, and look at the path following the -o option in the first line of output.] For example, on a Linux system the build directory path might be something like /tmp/build3877126492387157498.tmp. In that directory, look for the .cpp file created during compilation.
After you find the .cpp files for your sketch on both systems, copy them onto one system so you can compare them and check for differences. If they are different, one or the other ide might be corrupt or an incorrect include might be occurring.
If the .cpp files differ, compare the compile flags, the header files, etc. I think the flags and AVR header files should be the same on both systems, with the possible exception that MSW files might have carriage return characters after the newline characters. Also check the gcc versions. [I don't have an MSW system to try, but I'm supposing that gcc is used on both systems for AVR cross-compiling. Please correct me if I'm wrong.]
If the .cpp files match, then test the generated binary files to find out where they differ. (For example, if the sketch file is Blink21x.ino, binary files might be Blink21x.cpp.elf or Blink21x.cpp.hex.) If you have a .elf file on both systems [I don't know if the MSW system will generate .elf] use avr-objdump on the Linux system to produce a disassembled version of code:
avr-objdump -d Blink21x.cpp.elf > Blink21x.cpp.lst
Then use diff to locate differences between the two disassembly files. Enough information is available in the .lst file to identify your source line if the difference is due to how your source was compiled, as opposed to a difference in libraries. (In the latter case, enough information is given in the .lst file to identify which library routines differ.)
If you don't have an .elf file on the MSW system, you might try comparing the .hex files. From the location of the difference you can find the relevant line in the Linux-system .elf-disassembly file, and from that can identify a line of your code or a library routine.
I am trying to write a code which should be able to make duplicate copy of a file in any format. At the moment, I'm trying it for .pdf format. Here is the code that I have written:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream in("a.pdf", ios::binary);
if(in.fail())
{
cout<<"\nThe file couldn't be opened\n";
exit(0);
}
ofstream out("b.pdf", ios::binary);
while(!in.eof())
{
char buf[1000];
in.read(buf, sizeof(buf));
out<<buf;
}
in.close();
out.close();
return 0;
}
Now the problem is that the duplicate file either gets corrupted or is smaller/larger than the original file. And also doesn't contain any text.
I am witting this code for my computer networks project in which I have to send a file in any format from server to client.
I think this happens because you are using operator<< for output, which is designed to work with formatted strings, not binary data. std::ostream.write() is the counter part of read meant to be used with binary/unformatted data.
while(!in.eof())
{
char buf[1000];
in.read(buf, sizeof(buf));
out.write(buf, sizeof(buf));
}
operator<<(char*) probably stops on first "strange character". It also does not guarantee the output will be the same as input even in case of text, 'cause one can alter format output stream with formatting flags.
Actually I am not really sure what is the impact of ios::binary flag. Maybe you got confused that it would change behaviour of operator<< but it doesn't. I would expect it helps to alter buffering mode or something.
I would like to use ld's --build-id option in order to add build information to my binary. However, I'm not sure how to make this information available inside the program. Assume I want to write a program that writes a backtrace every time an exception occurs, and a script that parses this information. The script reads the symbol table of the program and searches for the addresses printed in the backtrace (I'm forced to use such a script because the program is statically linked and backtrace_symbols is not working). In order for the script to work correctly I need to match build version of the program with the build version of the program which created the backtrace. How can I print the build version of the program (located in the .note.gnu.build-id elf section) from the program itself?
How can I print the build version of the program (located in the .note.gnu.build-id elf section) from the program itself?
You need to read the ElfW(Ehdr) (at the beginning of the file) to find program headers in your binary (.e_phoff and .e_phnum will tell you where program headers are, and how many of them to read).
You then read program headers, until you find PT_NOTE segment of your program. That segment will tell you offset to the beginning of all the notes in your binary.
You then need to read the ElfW(Nhdr) and skip the rest of the note (total size of the note is sizeof(Nhdr) + .n_namesz + .n_descsz, properly aligned), until you find a note with .n_type == NT_GNU_BUILD_ID.
Once you find NT_GNU_BUILD_ID note, skip past its .n_namesz, and read the .n_descsz bytes to read the actual build-id.
You can verify that you are reading the right data by comparing what you read with the output of readelf -n a.out.
P.S.
If you are going to go through the trouble to decode build-id as above, and if your executable is not stripped, it may be better for you to just decode and print symbol names instead (i.e. to replicate what backtrace_symbols does) -- it's actually easier to do than decoding ELF notes, because the symbol table contains fixed-sized entries.
Basically, this is the code I've written based on answer given to my question. In order to compile the code I had to make some changes and I hope it will work for as many types of platforms as possible. However, it was tested only on one build machine. One of the assumptions I used was that the program was built on the machine which runs it so no point in checking endianness compatibility between the program and the machine.
user#:~/$ uname -s -r -m -o
Linux 3.2.0-45-generic x86_64 GNU/Linux
user#:~/$ g++ test.cpp -o test
user#:~/$ readelf -n test | grep Build
Build ID: dc5c4682e0282e2bd8bc2d3b61cfe35826aa34fc
user#:~/$ ./test
Build ID: dc5c4682e0282e2bd8bc2d3b61cfe35826aa34fc
#include <elf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#if __x86_64__
# define ElfW(type) Elf64_##type
#else
# define ElfW(type) Elf32_##type
#endif
/*
detecting build id of a program from its note section
http://stackoverflow.com/questions/17637745/can-a-program-read-its-own-elf-section
http://www.scs.stanford.edu/histar/src/pkg/uclibc/utils/readelf.c
http://www.sco.com/developers/gabi/2000-07-17/ch5.pheader.html#note_section
*/
int main (int argc, char* argv[])
{
char *thefilename = argv[0];
FILE *thefile;
struct stat statbuf;
ElfW(Ehdr) *ehdr = 0;
ElfW(Phdr) *phdr = 0;
ElfW(Nhdr) *nhdr = 0;
if (!(thefile = fopen(thefilename, "r"))) {
perror(thefilename);
exit(EXIT_FAILURE);
}
if (fstat(fileno(thefile), &statbuf) < 0) {
perror(thefilename);
exit(EXIT_FAILURE);
}
ehdr = (ElfW(Ehdr) *)mmap(0, statbuf.st_size,
PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(thefile), 0);
phdr = (ElfW(Phdr) *)(ehdr->e_phoff + (size_t)ehdr);
while (phdr->p_type != PT_NOTE)
{
++phdr;
}
nhdr = (ElfW(Nhdr) *)(phdr->p_offset + (size_t)ehdr);
while (nhdr->n_type != NT_GNU_BUILD_ID)
{
nhdr = (ElfW(Nhdr) *)((size_t)nhdr + sizeof(ElfW(Nhdr)) + nhdr->n_namesz + nhdr->n_descsz);
}
unsigned char * build_id = (unsigned char *)malloc(nhdr->n_descsz);
memcpy(build_id, (void *)((size_t)nhdr + sizeof(ElfW(Nhdr)) + nhdr->n_namesz), nhdr->n_descsz);
printf(" Build ID: ");
for (int i = 0 ; i < nhdr->n_descsz ; ++i)
{
printf("%02x",build_id[i]);
}
free(build_id);
printf("\n");
return 0;
}
Yes, a program can read its own .note.gnu.build-id. The important piece is the dl_iterate_phdr function.
I've used this technique in Mesa (the OpenGL/Vulkan implementation) to read its own build-id for use with the on-disk shader cache.
I've extracted those bits into a separate project[1] for easy use by others.
[1] https://github.com/mattst88/build-id