我有以下代码:
static char sessionid[SESSIONID_LEN+1] = { '\0' };
static void generate_sessionid() {
char set[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int len;
memset(sessionid, 0, sizeof(char) * SESSIONID_LEN);
for (len = 0; len < SESSIONID_LEN; len++) {
size_t index = (double) rand()/RAND_MAX*(sizeof(set) - 1);
sessionid[len] = set[index];
}
}
char *get_sessionid() {
if (strlen(sessionid) == 0) generate_sessionid();
char * dup = strdup(sessionid);
return dup;
}
我从另一个线程(其功能在不同的文件中定义)中调用get_sessionid()
。当我在get_sessionid()
的第2行中断并检查strdup()
返回的指针地址时,这是值:
0x7f7788c004f50
现在,当我从这个函数返回并检查线程函数中捕获的返回值时,返回值是不同的:
0xfffffffffc004f50
随后当我在此返回的指针值上调用strlen()
时,我得到一个SIGSEGV
,原因是Address 0xfffffffffc004f50 out of bounds
这两个文件是一个大型应用程序的一部分,该应用程序运行大约30个线程,并且在其他地方发生了更多的内存分配。我还认为内存已被其他线程泄露。但我想确保上述代码中没有错误。
我分别验证了上面的代码,一切正常,返回值没有损坏,即当与程序的其余部分隔离时,它完全正常。但我不明白为什么在整个程序的上下文中运行时返回值会发生变化。
修改(附件)
在线程函数中,我调用:
thread.c
#include <header.h>
login_sessionid = (char*)get_sessionid();
标题: header.h
char * get_sessionid(void);
编译器警告:
warning: implicit declaration of function ‘get_sessionid’ [-Wimplicit-function-declaration]
warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
以上警告均位于文件thread.c
答案 0 :(得分:4)
另一个文件中的代码没有意识到get_sessionid()
返回一个指针所以它假定它返回一个整数,然后用它来签名扩展它以创建一个指针。
您的编译器可能会警告未声明的函数;如果不是,请调高警告级别,直到警告级别为止。它也应该警告将整数转换为不同大小的指针。
注意编译器给出的警告。请记住,它比你更了解C语言。
还要确保编译器为您提供尽可能多的警告。如果您使用gcc
,则应使用gcc -Wall -Wextra -Werror -Wmissing-prototypes -Wold-style-definition -Wold-style-declaration
干净地编译;那是我目前的基准(-std=c11
或-std=c99
)。如果您的版本不支持旧式警告,您可以直接将其删除。
答案 1 :(得分:3)
除了@Jonathan Leffler所说的,如果多个线程可以调用此例程,则存在竞争条件,允许不同的线程获得不同的id,即使它们是单独的副本。
可能发生的一个例子:
通常,静态存储(没有互斥)和多个线程不会混合。这是多线程环境中singleton pattern的典型问题。