【问题标题】:C - String being changed by function unintentionallyC - 函数无意中更改了字符串
【发布时间】:2015-09-17 23:02:00
【问题描述】:

我最近一直在使用一些 C,而且我现在还比较新。我的主要问题是我传递给函数的字符串无意中被更改为一组新的随机字符。我很难解释我的问题,因为我有一堆代码,我不能全部分享。但这里是问题所在:

主函数中的这段代码:

char* name = "@";
Var v = NewVar(name, 0);
printf("%s\n", name);

打印:

Creating New Value w/ Name: @ 
@

-- 这是它应该打印的内容。但是,这段代码(在另一个函数中):

printf("Before: %s\n", split[counter]);
Var v = NewVar(split[counter], 0);
printf("After: %s\n", split[counter]);

打印:

Before: hi
Creating New Value w/ Name: �
After:�P�

“split”(来自上面的代码)只是一个这样定义的二维数组:

char** split = str_split(path, '/')

“NewVar()”函数如下:

Var NewVar(char *name, int value){
    printf("Creating New Value w/ Name: %s\n", name);
    Var v;
    v.value = value;
    v.name = name;
    v.varsLen = 0;
    v.vars = (Var*)malloc(sizeof(struct Vars));
    return v;
}

我之前已经多次注意到这个问题,但直到现在我都有解决方法。任何关于为什么会这样的建议或解释都会非常有帮助。

编辑: 这是一个完整的工作示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char** strSplit(char* base, const char* delim){
    char* result[0];
    char *token;
    char str[strlen(base)];
    strcpy(str, base);
    token = strtok(str, delim); 
    int counter = 0;
    while( token != NULL ) {
        result[counter] = token;
        token = strtok(NULL, delim);
        counter++;
    }
    char** split = malloc(counter * sizeof(char*));
    for(int i = 0; i < counter; i++){
        split[i] = malloc(sizeof(result[i])+1);
        result[i][strlen(result[i])] = '\0';
        split[i] = result[i];
    }
    split[counter] = 0;
    return split;
}

typedef struct Vars{
    char* name;
    struct Vars* vars;
    int value;
    int varsLen;
} Var;

Var NewVar(char *name, int value){
    printf("Creating New Value w/ Name: %s\n", name);
    Var v;
    v.value = value;
    v.name = name;
    v.varsLen = 0;
    v.vars = (Var*)malloc(sizeof(struct Vars));
    return v;
}

void test(char** split){
    char* name = split[0];
    Var v = NewVar(name,0);
    printf("After: %s\n", name);
}

int main(int argc, char const *argv[])
{
    char* name = "@";
    Var v = NewVar(name, 0);
    printf("%s\n", name);
    char** split = strSplit("@/dir1/dir2", "/");
    printf("Before: %s\n", split[0]);
    test(split);
    return 0;
}

打印出来的:

Creating New Value w/ Name: @
@
Before: @
Creating New Value w/ Name: @
After: 

【问题讨论】:

  • C 不支持方法。如果您的意思是函数,请更正。
  • 您可能无法发布所有代码,但您需要发布一个我们可以推理的示例。比如,你能把str_split()的定义贴出来吗?
  • @tgm1024:该标准不要求将auto 变量放在堆栈上。如果使用堆栈,static 局部变量也不会放在那里。
  • 如果Varstruct,那很好。问题更有可能是您将name 指针 复制到新的Var。如果另一个函数更改了Varname 成员,它将导致修改原始字符串。请在您的问题中包含Var 的定义。
  • char* result[0];?呸呸呸。错了。

标签: c string pointers methods


【解决方案1】:

让我们剖析str_split(),好吗?

char** strSplit(char* base, const char* delim){
    char* result[0];

我们的第一个错误。你不能有零长度的数组。此外,您稍后会使用该数组,因此即使您可以拥有长度为零的数组,也无法对它们进行索引。

    char *token;
    char str[strlen(base)];
    strcpy(str, base);

下一个错误。 str 太小,无法容纳 base,因为 strlen() 不算空终止符。

    token = strtok(str, delim); 
    int counter = 0;
    while( token != NULL ) {
        result[counter] = token;

滥用result

        token = strtok(NULL, delim);
        counter++;
    }
    char** split = malloc(counter * sizeof(char*));

记住这一点,split 有足够的空间容纳 counter char *s...

    for(int i = 0; i < counter; i++){
        split[i] = malloc(sizeof(result[i])+1);

混淆了strlen()sizeof()

        result[i][strlen(result[i])] = '\0';

没用。如果somestring[strlen(somestring)] 还不是'\0',它就不会是strlen(somestring)

        split[i] = result[i];

这会泄漏为split[i] 分配的内存并保留指向str 的指针,当函数返回时,该指针超出范围。替换为strcpy()

    }
    split[counter] = 0;

你还记得split 有多少空间吗?

    return split;
}

【讨论】:

    【解决方案2】:

    你不知道name 的传入值会发生什么。如果它是在堆栈上分配的,它将被覆盖。分配给v.name 时使用 strcpy,您会很安全。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-29
      • 2012-10-23
      • 1970-01-01
      • 2012-10-09
      • 1970-01-01
      • 1970-01-01
      • 2021-02-24
      • 1970-01-01
      相关资源
      最近更新 更多