所以这很奇怪 - 下面是我创建tokenizer对象的代码和主要方法:
struct TokenizerT_ {
char * sep;
char * toks;
};
TokenizerT *TKCreate(char *separators, char *ts) {
if (ts==NULL) {
return NULL;
}
int lin = (int) strlen(separators);
char yr[lin];
yr[0] = *separators;
int lim = 1;
int h = 1;
for(h=1; h<strlen(separators); h++){
char tmp = *(separators+h);
int z=0;
for (z=0; z<lim; z++) {
if (tmp==yr[z]) {
z=-1;
break;
}
}
if(z>-1){
yr[h] = tmp;
lim++;
}
}
TokenizerT inu = {yr, ts};
printf("%s\n", inu.sep);
return &inu;
}
int main(int argc, char **argv) {
char * arr = argv[1];
char * y = argv[2];
TokenizerT jer = *TKCreate(arr, y);
printf("%s\n", jer.sep);
printf("%s\n", jer.toks);
return 0;
}
如果我使用参数“tes”和“testing”运行程序,我会得到以下结果: TES TES 测试
但是,如果我用TKCreate中的printf语句运行程序注释掉,我得到:
测试。
printf(“%s \ n”,jer.sep)停止工作,除了在TKCreate中注释掉printf语句之外,我没有对代码做任何事情。为什么会这样?
答案 0 :(得分:3)
这里有很多问题:
inu
是一个局部变量。你返回它的地址。当您尝试从main
中的该地址读取时,您正在访问不再在范围内的变量。这是未定义的行为。sep
的{{1}}字段已分配inu
。现在,yr
是一个局部变量,一个字符数组,它衰减到一个指针。同样,一旦函数返回就访问它意味着访问其范围已结束的变量。再次,未定义的行为。我建议进行以下更改:
yr
动态分配字符数组。最重要的是,我怀疑你还有其他问题。在我看来,malloc
不是以空值终止的,并且某些元素可能根本不会被初始化。这是故意的吗?也许你真的打算在写yr
时初始化yr
等于separators
。请注意,您的代码只分配一个字符。要动态分配yr[0] = *separators
,并将其初始化为等于yr
,您可以写:
separators
为什么多次拨打yr := malloc(strlen(separators)+1);
strcpy(yr, separators);
?您似乎将其称为strlen(separators)
次。你应该只调用一次。
答案 1 :(得分:2)
在C中,您永远不能返回指向本地函数变量的指针。嗯,你可以,但它不会起作用。即使似乎工作,它只是在等待一个不工作的好机会。
所以你绝对不能这样做:
TokenizerT inu = {yr, ts};
return &inu;
您需要做的是传递指向要构建的对象的指针,或使用malloc
分配新的对象。如果您使用malloc
,则需要稍后记住free
该对象。而且由于Windows及其多个C运行时,free
函数内部的对象是一个非常好的主意。因为如果您要在库中使用代码,并在调试运行时使用malloc
并在发布运行时使用free
,那么就会发生错误。
因此对于malloc示例:
struct box* create_box(int x, int y) {
struct box* b = malloc(sizeof(*b));
if(!b) abort();
b->x = x;
b->y = y;
return b;
}
void destroy_box(struct box* x) {
free(x);
}
用于传递对象:
void init_box(struct box* b, int x, int y) {
b->x = x;
b->y = y;
}
void f() {
struct box b;
init_box(&b, 10, 20);
}
答案 2 :(得分:0)
您需要为要从函数返回的对象分配内存。这会将对象放在堆栈(永久内存)副本上堆栈(当前函数结束后由程序回收的内存)。
您可以通过在TKCreate函数中进行这些更改来实现此目的:
TokenizerT *TKCreate(char *separators, char *ts) {
...
# change 'char yr[lin];' to:
char* yr = (char*)malloc(lin * sizeof(char));
....
TokenizerT* inu = (TokenizerT*)malloc(sizeof(TokenizerT));
inu->sep = yr;
int->yoks = ts;
printf("%s\n", inu->sep);
return inu;
}
您还可以通过仅共享对象的一个副本来清理main()函数。完成后,您可以在任何分配内存上调用free():
int main(int argc, char **argv) {
char * arr = argv[1];
char * y = argv[2];
TokenizerT jer* = TKCreate(arr, y);
printf("%s\n", jer->sep);
printf("%s\n", jer->toks);
free(jer);
return 0;
}