I'm wondering why this code isn't working as expected.
typedef char uint8;
int main(int argc, const char * argv[]) {
// insert code here...
uint8 number_1 = 3;
uint8 number_2 = 1;
uint8 *PointerToNumber = &number_1;
printf("%d \n", *PointerToNumber);
++PointerToNumber;
printf("%d \n", *PointerToNumber);
return 0;
}
This program prints 3 and -112. However shouldn't it print 3 and 1 if the stack grows continuously?
So if I'm pointing to number_1 and then increasing the pointer address of type uint8 shouldn't it then point to number_2 since it was declared right after number_2?
++PointerToNumber;
printf("%d \n", *PointerToNumber);
is cause for undefined behavior. It's pointless trying to justify any behavior. The behavior of the program could change with changes to optimization level, different compiler options, and a different compiler.
In this case, an optimizer could choose not to allocate any space for number_2 since it is not used in the function.
All right as someone commented, number-2 is probably at the next lower address after number_1.
So instead of doing ++PointerToNumber, --PointerToNumber creates the expected result (printing "1").
Related
Below is the program:
#include <stdio.h>
#include<stdlib.h>
int *glob_var;
int* copy(void *a,int size)
{
int *t=(int *)calloc(1,sizeof(int));
int i;
int *glob_var=(int *)calloc(size,sizeof(int));
printf("glob_var=%p\n",glob_var);
printf("a=%p\n",a);
t=glob_var;
for(i=0;i<size;i++)
{
*glob_var=*(int *)a;
glob_var++;
(int *)a++;
// printf("a=%p\n",a);
}
glob_var=t;
for(i=0;i<10;i++)
{
printf("%d\t",*glob_var);
glob_var++;
}
glob_var=t;
printf("\n%p\n",glob_var);
return t;
}
int main() {
// Write C code here
int a=0x123456,i;
int *var=(int *)calloc(10,sizeof(int));
int *temp;
temp=var;
for(i=0;i<10;i++)
{
*var=i;
var++;
}
var=temp;
for(i=0;i<10;i++)
{
printf("%d\n",*var);
var++;
}
var=temp;
printf("var=%p\n",var);
glob_var=copy(var,10);
printf("%p\n",glob_var);
for(i=0;i<10;i++)
{
printf("%d\t",*glob_var);
glob_var++;
}
return 0;
}
However, the output I got is :
0 16777216 65536 256 1 33554432 131072 512 2 50331648
I was expecting: 0 1 2 3 4 5 6 7 8 9.
But, in the copy() function, if I replace (int *)a++; with a=(int *)a+1; it is working.
My question is: What is wrong with the current program?
Arithmetic on a pointer-to-void (void*) is not allowed in C1 and your compiler should warn you about that (at the very least) in the following line:
(int *)a++;
When I compile your code (using the clang-cl compiler in Visual Studio), I do, indeed, get two warnings for that line:
warning : arithmetic on a pointer to void is a GNU extension [-Wpointer-arith]
warning : expression result unused [-Wunused-value]
The first of these addresses the issue mentioned in my opening line (and discussed in the footnote) but it is the second that should be ringing alarm bells. That shows that the cast isn't working as intended – it is actually applied to the result of the a++ operation, because the cast has lower precedence than the post-increment.
However, when you use a = (int *)a + 1;, then all is working as intended, because the a pointer is cast to an int* before the arithmetic is performed (and then implicitly cast back to a void* for the assignment).
(There are other issues in your code, like the re-declaration of glob_var in your function, and the use of non-void pointers as arguments for the %p format specifier in several printf calls – but these are not really related to your reported problem. Also, this is worth a read: Do I cast the result of malloc?)
1 Some C compilers, such as GCC, do allow arithmetic on void* pointers, but I do not know what the 'base unit size' is for such operations. One would have to read the GCC manual to determine that, but it may very well by just 1, rather than the sizeof(int) required for your program, as presented, to work. Indeed, if that assumption is correct, and sizeof(int) is 4 on your platform, it would explain the three "garbage values" between successive 'real' data in your output.
I missed a problem when I doing my homework.
Computer memory in the storage of data where there are big-endian storage and small-endian storage two methods, in order to detect a machine storage method, a student wrote the following procedure:
union NUM {
int a;
char b;
} num;
int main(){
num.b = 0xff;
if (num.a! = 0xff)
printf ("bigend");
else
printf ("smallend");
return 0;
}
But he found the program running on the x86 machine, print out is actually 'bigend', which is clearly wrong. Do you know where the problem is?
How should this program be modified?
I have asked my teacher, the topic is correct. I have found some information in some websites, but it makes me more confused. Why this question is not incorrect? And where the problem actually is?
Assuming an int (and therefore the union as a whole) is 4 bytes, writing to num.b only writes to one of those 4 bytes, leaving the rest uninitialized. Subsequently reading num.a reads those uninitialized bytes, invoking undefined behavior.
The bytes in the union must be set to all 0s so that the content is well defined.
#include <stdio.h>
#include <string.h>
union NUM {
int a;
char b;
} num;
int main(){
// set all bytes of num to 0 first
memset(&num, 0, sizeof(num));
num.b = 0xff;
if (num.a! = 0xff)
printf ("bigend");
else
printf ("smallend");
return 0;
}
Type-punning is undefined behavior in C. When you read num.a you are violating the strict aliasing rules, so the compiler is allowed to generate code that may give back anything. Which it does.
To avoid this, you need to use memcpy():
int a = 0x00010203;
char bytes[sizeof(a)];
memcpy(bytes, &a, sizeof(a));
if(bytes[0] == 03) {
printf("small endian\n");
} else ...
I am having trouble to run this c code. When I do i get segmentation fault and an error with 'return' return 0xdeadbeef;
Anyone have any suggestions?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int lame(unsigned int size, unsigned int value){
unsigned int array1[4];
unsigned int array2[6];
array2[5] = value;
memcpy(&array1, &array2, size * sizeof(unsigned int));
return 1;
}
void awesome(){
printf("awwwwwww yeaaahhhhh! All awesome, all the time!\n");
}
main(unsigned int argc, char ** argv){
unsigned int size, value;
size = strtoul(argv[1], 0, 10);
value = strtoul(argv[2], 0, 16);
if(!lame(size, value)){
awesome();
}
else{
printf("I am soooo lame :(\n");
}
return 0xdeadbeef;
}
I said that there was "at least one bug on almost every line of your code" and now I will list them. If I don't have any comments on a line, there are no bugs on that line, but you also need to read up on proper code formatting and style.
int lame(unsigned int size, unsigned int value){
unsigned int array1[4];
unsigned int array2[6];
array2[5] = value;
memcpy(&array1, &array2, size * sizeof(unsigned int));
return 1;
}
Undefined behavior on the memcpy line if size is larger than 4. Since size is taken from user input, this program contains a buffer overflow vulnerability, albeit one that might be hard to exploit. (You need to read "Smashing the Stack for Fun and Profit.")
This function has no externally visible side effects. The compiler may, and probably will, delete all of its code except the return 1.
Functions that always return the same constant value should be refactored to return void. Functions that are not used outside the current file should be declared static.
void awesome(){
printf("awwwwwww yeaaahhhhh! All awesome, all the time!\n");
}
This use of printf can be replaced by puts. Functions that are not used outside the current file should be declared static.
main(unsigned int argc, char ** argv){
The first argument to main must have type int, not unsigned int. The return type (which must be int, not void) is missing; many compilers will tolerate this (treating it as implicitly returning int) for backward compatibility with pre-C89 code, but it's still Wrong.
unsigned int size, value;
size = strtoul(argv[1], 0, 10);
value = strtoul(argv[2], 0, 16);
Both size and value should be unsigned long for consistency with what strtoul returns.
Undefined behavior if there are fewer than two command-line arguments.
Need to check both calls to strtoul for failure. This is nontrivial; read the EXAMPLES section of the OpenBSD manpage for strtoul to learn how to do it correctly.
However, props for using strtoul rather than atoi (which you can't check for failure) or sscanf (which has undefined behavior on integer overflow).
if(!lame(size, value)){
awesome();
}
else{
printf("I am soooo lame :(\n");
}
The compiler can and will determine that lame always returns 1, and optimize out the call to awesome. (In fact, it would be entitled to optimize out everything but the above printf, as all control flow paths either trigger undefined behavior or they reach this printf, and there are no other externally visible effects. The compilers I have readily to hand are not quite that clever, but they do remove the if-then-else and all the code inside lame.)
This use of printf can also be replaced by puts.
You will automatically become 23% less lame the moment you stop calling yourself lame.
return 0xdeadbeef;
The value returned by main is meaningful. 0 means success of the overall program, any other value means some sort of failure. Always return 0 unless you intend to indicate failure. Also, only values in the range [0, 127] can be reliably received by the parent process cross-platform; 0xdeadbeef is Right Out.
In your screenshot, main returned void instead of having a missing return type; that plus a return statement with a value should have caused the program to fail to compile. Your compiler might tolerate it in main, though.
I have a piece of code where I am trying to return the square of the value pointed to by *ptr.
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
main()
{
int a=8,t;
t=square(&a);
printf("%d",t);
}
Its working fine for me but author of this code said it might not work because of following reason:
Because it's possible for the value of *ptr to change unexpectedly, it is possible for a and b to be different. Consequently, this code could return a number that is not a square!. The correct way to do is
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
I really wanted to know why he said like that?
The idea of the volatile keyword is exactly to indicate to the compiler that a variable marked as such can change in unexpected ways during the program execution.
However, that does not make it a source of "random numbers" - it just advises the compiler - what is responsible for actually changing the variable contents should be another process, thread, some hardware interrupt - anything that would write to the process memory but not inlined in the function where the volatile declaration finds itself. In "older times" (compilers with less magic) everything it did was preventing the compiler from caching the variable value in one of the CPU registers. I have no idea on the optimisations/de-optimistions strategies triggered by it by modern compilers - but it will at least do that.
In the absense of any such external factor, a "volatile" variable is just like any other. Actually - it is just like any other variable - as variables not marked as volatile can also be changed by the same external causes (but the compiled C code would not be prepared for that in this case, which might lead to incorrect values being used).
Since the question has an accepted and correct answer, I will be brief: here is a short program that you can run to see the incorrect behavior happening for yourself.
#include <pthread.h>
#include <math.h>
#include <stdio.h>
int square(volatile int *p) {
int a = *p;
int b = *p;
return a*b;
}
volatile int done;
void* call_square(void* ptr) {
int *p = (int*)ptr;
int i = 0;
while (++i != 2000000000) {
int res = square(p);
int root = sqrt(res);
if (root*root != res) {
printf("square() returned %d after %d successful calls\n", res, i);
break;
}
}
done = 1;
}
int main() {
pthread_t thread;
int num = 0, i = 0;
done = 0;
int ret = pthread_create(&thread, NULL, call_square, (void*)&num);
while (!done) {
num = i++;
i %= 100;
}
return 0;
}
The main() function spawns a thread, and modifies the data being squared in a loop concurrently with another loop calling the square with a volatile pointer. Relatively speaking, it does not fail often, but it does so very reliably in less than a second:
square() returned 1353 after 5705 successful calls <<== 1353 = 33*41
square() returned 340 after 314 successful calls <<== 340 = 17*20
square() returned 1023 after 5566 successful calls <<== 1023 = 31*33
First understand what's volatile: Why is volatile needed in C?
and then, try to find answer by yourself.
It's a game of volatile and hardware world. :-)
Read answer given by Chris Jester-Young:
volatile tells the compiler that your variable may be changed by other means, than the code that is accessing it. e.g., it may be a I/O-mapped memory location. If this is not specified in such cases, some variable accesses can be optimised, e.g., its contents can be held in a register, and the memory location not read back in again.
If there is more than one thread, the value the pointer points to might change inbetween statement "a = *ptr" and statement "b = *ptr". Also: you want the square of a value, why put it into two variables?
In the code you present then there is no way for the variable a that is defined in your main to be modified whilst square is running.
However, consider a multi-threaded program. Suppose that another thread modified the value to your your pointer refers. And suppose that this modification took place after you had assigned a, but before you had assigned b, in the function sqaure.
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
//the other thread writes to *ptr now
b = *ptr;
return a * b;
}
In this scenario, a and b would have different values.
The author is correct (if *ptr will be changed by other threads)
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
//between this two assignments *ptr can change. So it is dangerous to do so. His way is safer
b = *ptr;
return a * b;
}
Because the value of the pointer *ptr might change between the first affection and the second one.
I don't think the value of *ptr can change in this code barring an extremely unusual (and non-standards-compliant) runtime environment.
We're looking at the entirety of main() here and it's not starting up other threads. The variable a, whose address we are taking, is a local in main(), and main() doesn't inform any other function of that variable's address.
If you added the line mysterious_external_function(&a); before the t=square(&a) line, then yes, mysterious_external_function could start a thread and diddle the a variable asynchronously. But there's no such line, so as written square() always returns a square.
(Was the OP a troll post, by the way?)
I see some answers with *ptr can be changed by other threads. But this cannot happen since *ptr is not a static data variable. Its a parameter variable and local and parameter variables being hold inside stack. Each thread has its own stack section and if *ptr has been changed by another thread, it should not effect the current thread's.
One reason why the result might not give the square can be an HW interrupt might happen before assigning b = *ptr; operation as indicated below:
int square(volatile int *ptr) {
int a,b;
a = *ptr; //assuming a is being kept inside CPU registers.
//an HW interrupt might occur here and change the value inside the register which keeps the value of integer "a"
b = *ptr;
return a * b;
}
When the following code is compiled with LLVM Compiler, it doesn't operate correctly.
(i doesn't increase.)
It operates correctly when compiling with GCC 4.2.
Is this a bug of LLVM Compiler?
#include <stdio.h>
#include <string.h>
void BytesFromHexString(unsigned char *data, const char *string) {
printf("bytes:%s:", string);
int len = (int)strlen(string);
for (int i=0; i<len; i+=2) {
unsigned char x;
sscanf((char *)(string + i), "%02x", &x);
printf("%02x", x);
data[i] = x;
}
printf("\n");
}
int main (int argc, const char * argv[])
{
// insert code here...
unsigned char data[64];
BytesFromHexString(data, "4d4f5cb093fc2d3d6b4120658c2d08b51b3846a39b51b663e7284478570bcef9");
return 0;
}
For sscanf you'd use %2x instead of %02x. Furthermore, %2x indicates that an extra int* argument will be passed. But you're passing an unsigned char*. And finally, sscanf takes a const char* as first argument, so there's no need for that cast.
So give this a try :
int x;
sscanf((string + i), "%2x", &x);
EDIT : to clarify why this change resolves the issue : in your code, sscanf tried to write sizeof(int) bytes in a memory location (&x) that could only hold sizeof(unsigned char) bytes (ie. 1 byte). So, you were overwriting a certain amount of memory. This overwritten memory could very well have been (part of) the i variable.
From the compiler side of things the reason for this code behaving differently is that gcc and llvm (or any other compiler) may lay out the stack differently. You were likely just clobbering something else on the stack before that you didn't need for this example, but with the different layout for the llvm compiler you were clobbering something more useful.
This is another good reason to use stack protectors when debugging a problem (-fstack-protector-all/-fstack-protector). It can help flush out these issues.