Overlapping memory with sprintf(snprintf)

社会主义新天地 提交于 2020-07-10 11:40:29

问题


Edit: What about if we had this

char value_arr[8];    
// value_arr is set to some value
snprintf(value_arr, 8, "%d", *value_arr);

is this behavior defined?


Let's say for some ungainly reason I have

char value_arr[8];
// value_arr is set to some value
int* value_i = reinterpret_cast<int*>(value_arr);

snprintf(value_arr, 8, "%d", *value_i); // the behaviour in question

Is there a guarantee that, for example, if *value_i = 7, then value_arr will take on the value of "7". Is this behavior defined? Such that value_i is first dereferenced, then passed by value, and then formatted, then stored into the array.

Normally, the value of *value_i can be expected to not change, but storing the string into value_arr violates that.

It seems to function as expected when I test it, but I can't seem to find a definitive answer in the documentation. The function signature has ..., which to my knowledge has something to do with va_list, but I'm afraid I'm not very knowledgable on the workings of variadic functions.

int sprintf (char* str, const char* format, ... );

回答1:


For the original code, evaluating the expression *value_i causes undefined behaviour by violating the strict aliasing rule. It is not permitted to alias a char array as int.

For the edited code, snprintf(value_arr, 8, "%d", *value_arr);, it is fine and will format the character code of the first character in the array. Evaluation of function arguments is sequenced-before entering the function. (C++17 intro.execution/11)




回答2:


It's undefined behaviour; You use a pointer of type int* to point to an object of type char[8] with different / relaxed alignment requirements compared to int*. Dereferencing this pointer then yields UB.




回答3:


The following can be found at https://en.cppreference.com/w/cpp/io/c/fprintf:

If a call to sprintf or snprintf causes copying to take place between objects that overlap, the behavior is undefined.

I would interpret your example to fall into this case and as such it would be classified as Undefined Behaviour, according to this page.

Edit: Some more details at https://linux.die.net/man/3/snprintf:

Some programs imprudently rely on code such as the following

sprintf(buf, "%s some further text", buf);

to append text to buf. However, the standards explicitly note that the results are undefined if source and destination buffers overlap when calling sprintf(), snprintf(), vsprintf(), and vsnprintf(). Depending on the version of gcc(1) used, and the compiler options employed, calls such as the above will not produce the expected results.



来源:https://stackoverflow.com/questions/53016983/overlapping-memory-with-sprintfsnprintf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!