LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   need solution for g++ warning on 64bit (https://www.linuxquestions.org/questions/programming-9/need-solution-for-g-warning-on-64bit-420859/)

Thinking 03-02-2006 03:39 AM

need solution for g++ warning on 64bit
 
in my prog i'm using threads
so i use pthread_create function to start them
one argument for my thread is e.g. an int value
example:
int somevar = 10;
pthread_create(&threadstruct,NULL,threadfunc,(void*)somevar);

this worked on my 32bit test environment perfectly and for the 64bit stuff it works too, but i get a warning

the first warning is: warning: cast to pointer from integer of different size
i understand why i get this, but i'm not sure, how i can solve the problem
well, on 64bit int is 4byte and void* is 8byte in size (i tested it with sizeof())
so i tried casting like this: (void*)(long*)somevar but i got the same warning
Q1: any hint wo i can remove the warning, with good valid code
i don't want to ignore such stuff

a possible solution could be something like this:
i got a similar problem on the "other" side of the thread
Code:

static void* class::threadfunc(void *arg){
  int somevar = (int)arg;
}

using the code above i got this warning: warning: cast from pointer to integer of different size
the solution was:
Code:

  int somevar = (int)(long)arg;

Wim Sturkenboom 03-02-2006 04:32 AM

Code:

pthread_create(&threadstruct,NULL,threadfunc,(void*)somevar);
the last argument is incorrect. You must pass the address of somevar. The way you're doing it implies that the value in somevar contains the address.
Change it to:
Code:

pthread_create(&threadstruct,NULL,threadfunc,(void*)&somevar);
At the other side (in threadfunc) you receive a pointer. To get the int-value of the variable where the pointer points to (and not the address where it points to) use:
Code:

somevar=(int)*arg
PS: you were lucky that your 32-bit code worked.

Thinking 03-02-2006 04:53 AM

@Wim Sturkenboom

i'm not sure what you mean

cause: if i cast the int (value 10) to a pointer i have a pointer of value 10, so the pointer points to e.g. 0xA memory address

so its absolutly no problem to do it like i did, and it works without a problem

Q: why should it be a problem?

Quote:

The way you're doing it implies that the value in somevar contains the address.
no it doesn't
cause: the value in somevar has nothing to do with a address and the value in the pointer! which is used as an argument, HAS the value of the value of somevar
SO it CANt be a problem, CAUSE i'm not using the argument AS a pointer

hmm, correct?

if i would do this:
Code:

prog:
    pthread_create(&threadstruct,NULL,threadfunc,somevar);
void* threadfunc(void *arg){
  int value = (int)*arg;  /// WWOOAAHH, seg fault
}

i get a seg fault

for me, (at this point right now) i think i understand why my code works without a problem and i think it will in future, cause the pointer isn't used as a pointer ;-)
it works on the 64bit arch too, but i get warnings during compile time, but it works
btw: this wasn't my idea, i got this from "unix network programming" book (<-- very good book!)

dmail 03-02-2006 05:31 AM

Thinking Wim Sturkenboom is correct you want to pass the address of somevar.
Quote:

The way you're doing it implies that the value in somevar contains the address.
Quote:

no it doesn't

Yes it does.


Your code example should read
if C
Code:

prog:
    pthread_create(&threadstruct,NULL,threadfunc,&somevar);
void* threadfunc(void *arg){
  int* value = arg;
}

if C++
Code:

prog:
    pthread_create(&threadstruct,NULL,threadfunc,(void*)&somevar);
void* threadfunc(void *arg){
  int* value = (int*)arg;
}


Thinking 03-02-2006 06:01 AM

why?
cause this would have the problem that i use the address of a local var
so i will get a seg fault

btw:
Quote:

Thinking Wim Sturkenboom is correct you want to pass the address of somevar.
no i don't
i don't want to pass the address of somevar, i want to pass the value of somevar

Wim Sturkenboom 03-02-2006 07:56 AM

Quote:

Originally Posted by Thinking
why?
cause this would have the problem that i use the address of a local var
so i will get a seg fault

No, you will not get a segfault. If you get a segfault, there is a coding mistake.

Quote:

Originally Posted by Thinking
i don't want to pass the address of somevar, i want to pass the value of somevar

You can only do so by passing the pointer (so the address) as that is what pthread_create requires.

dmail 03-02-2006 09:16 AM

Quote:

Originally Posted by Thinking
why?
cause this would have the problem that i use the address of a local var
so i will get a seg fault

btw:

no i don't
i don't want to pass the address of somevar, i want to pass the value of somevar

Ok it seems you know best.
End of help.

Thinking 03-02-2006 09:57 AM

@dmail
hey, i simply don't know why and there wasnt a explanation why i did something wrong
this means nobody said why it was wrong, only that it was wrong ;-)

@Wim Sturkenboom
Quote:

No, you will not get a segfault. If you get a segfault, there is a coding mistake.
yeah, damn, your right
forgot it
hmm, the problem i ran into using the address of the local variable was that the variable changed so fast, that i created 2 threads which got the SAME value of the local var, altough it should be different
example: thread1 is created and the pointer to a local var is the arg
execution of thread1 isn't done already
thread2 is created and the value of local var has changed
now thread1 and thread2 begin to execute --> i get 2 threads with the same value, but thats a failure (this scenario was my problem i had already, thats why i use the method explained a few posts before)

Quote:

You can only do so by passing the pointer (so the address) as that is what pthread_create requires.
until now i don't know what you mean
cause:
1. i look in the man page of pthread_create
2. i see, the argument for the thread "should" be a pointer (i see there stands void* arg)
3. i cast a value (from local var int simplevar) to a void* pointer, so the value of the pointer is the value of the local var
this means the pointer points to 0xA (<< just an example)
4. the thread is created and i need the value of the local variable of the function who created the thread
i simply cast back: int x = (int)arg;
this means i write the value of the pointer (the address it points to = 0xa) as a value in the local variable of the thread function
5. i have the value from simplevar in my local var x of the thread
6. i compile it - it works
7. i run it - it works
8. i debug it - it has the correct values all the time

the above points make me think, that i don't understand why my code is wrong (as you said)

another example:
Code:

#include <stdio.h>

void test(void *x);

int main(int argc,char **argv){
    int c = 10;
    test((void*)c);
    return 0;
}

void test(void *x){
    printf("%d %p\n",(int)x,x);
}

why does the above code work? it should print 10 0xa and it does

another point: why is a book (which is very very good) using the same technique? i'm sure the author knows what the does, cause the technique is used in the chapter where different server architectures are explained, this means they have to be stable

BTW: i'm not sure, but the discussion here goes into the wrong direction (from my point of view)
i just needed a hint for resolving the warnings (I GET THE WARNINGS ONLY ON 64bit!)
but maybe i'm really a complete idiot as dmail seem to think

ask.jackal 03-02-2006 11:35 AM

Can u try

pthread_create(&threadstruct,NULL,threadfunc,(void*)(long)somevar);

Assume ILP architecture for ur 64 bit platforms

John Arackal

Thinking 03-02-2006 02:59 PM

aarrgghh
yep, it worked
orz
thx@ll

Wim Sturkenboom 03-03-2006 12:06 AM

Quote:

Originally Posted by Thinking
Code:

1 #include <stdio.h>
 2
 3 void test(void *x);
 4
 5 int main(int argc,char **argv){
 6    int c = 10;
 7    test((void*)c);
 8    return 0;
 9 }
10
11 void test(void *x){
12    printf("%d %p\n",(int)x,x);
13 }


Let's try to analyze the code. In line 6, you create a variable with the content 10. In line 7, you cast the content of the variable to a pointer-to-void and pass it to a function the requires a pointer-to-void. The only reason you have done this, is to keep the compiler happy. And yes, you're passing the value 10 to the function (as a copy of c).
This value is passed on the stack. When the function is started, it will read this value from the stack.
Now the function itself. It takes a pointer-to-void, so x is a variable that points to a void. In line 12 you print x and not the variable where x points to (so you don't use x as a pointer).
When the function is terminated, the stack is cleared (so x does not exist anymore)..
Nothing wrong with that code, it does what you told it to do but probably not what you thought it will do. I will try to show this below.

Let's modify the code slightly. After line 12, add an assignement and add an additional printf after line 7
Code:

1 #include <stdio.h>
 2
 3 void test(void *x);
 4
 5 int main(int argc,char **argv){
 6    int c = 10;
 7    test((void*)c);
8    printf("c = %d\n",c);
 9    return 0;
10 }
11
12 void test(void *x){
13    printf("%d %p\n",(int)x,x);
14    x=0;
15 }

You have now modified x, so x now points to somewhere else (it's still a pointer). Remember, x is on the stack.
When returning from the function, x is removed from the stack and c still contains the original value (as you passed a copy on the stack).

To get this right, below the final version.
Code:

1 #include <stdio.h>
 2
 3 void test(void *x);
 4
 5 int main(int argc,char **argv){
 6    int c = 10;
7    test((void*)&c);
 8    printf("c = %d\n",c);
 9    return 0;
10 }
11
12 void test(void *x){
14    printf("%d %p\n",(int)x,x);
15    *(int*)x=0;
      |  |
      |  +-- cast pointer-to-void to pointer-to-int
      +----- change variable where x points to, not x itself

16 }

We now pass (a copy of) the address of c to the function (line 7, casted to pointer-to-void), so x in the function will contain the address (and not the content). In line 15 we assign a new value to the variable where x points to (so we assign a new value to variable c). The line looks complex. To assign the value to the variable where x points to, we need to use *x; as x is a pointer-to-void, we have to cast to a pointer-to-int.

With regards to the compiler. It highly depends on the compiler which warnings you get in which situation. If you're using gcc, you now probably use a different version now and that might be more sensitive to the coding. Warnings are there to tell you that you might not get the desired result, not that you by definition do something wrong.
However, you better get rid of them. You might know today how it works, but have forgotten tomorrow. Next time you compile you might not understand why you have warnings. Andf if someone else ever has to maintain the code, he/she will go nuts (at least I would)

Hope that it helps in the understanding.

Last but not least: the modified code as I would have written it
Code:

1 #include <stdio.h>
 2
 3 void test(void *x);
 4
 5 int main(int argc,char **argv){
 6    int c = 10;
7    test((void*)&c);
 8    return 0;
 9 }
10
11 void test(void *x){
12    printf("%d %p\n",*(int*)x,x);
13 }

This will print the value of the variable where x points to as an int (c) as well as the address where x points to (address of c).

Thinking 03-03-2006 12:10 PM

i think i know what you mean
but that's not what i wanted to do

i just passed the socket descriptor to the thread and the main prog does just nothing with it
thats why i use it this way
only the thread needs to know about the descriptor, the main prog has, after calling pthread_create, nothing to do with the descriptor any more

i understand what you mean, but it can decrease performance if i would need to use mutex or malloc for locking/creating memory just for the descriptor

thats why i do it this way
i'm sure its not the best way, but i tested it very often and it runs ;-)

btw: thx for taking care of this


All times are GMT -5. The time now is 12:41 PM.