简体   繁体   English

C - 函数无意中更改了字符串

[英]C - String being changed by function unintentionally

I've been using some C lately and I'm relatively new right now.我最近一直在使用一些 C,现在我还比较新。 My main problem is that a string I pass to a function is getting changed to a new set of random characters unintentionally.我的主要问题是我传递给函数的字符串无意中更改为一组新的随机字符。 It's difficult for me to explain my problem because I have a bunch of code and I can't share it all.我很难解释我的问题,因为我有一堆代码,我无法全部共享。 But here are the areas where the problem is:但这里是问题所在的领域:

This code in the main function:主函数中的这段代码:

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

Prints:印刷:

Creating New Value w/ Name: @ 
@

-- which is what it should print. ——这是它应该打印的内容。 However, this code (in another function):但是,此代码(在另一个函数中):

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

Prints:印刷:

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

"split" (from the code above) is just a 2d array defined as such: “split”(来自上面的代码)只是一个定义如下的二维数组:

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

The "NewVar()" function is the following: “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;
}

I've noticed this problem many times before, but up until now I've had work-arounds.我以前多次注意到这个问题,但到目前为止我已经有了解决方法。 Any advice or explanation as to why this is would be super helpful.关于为什么会这样的任何建议或解释都会非常有帮助。

Edit: This is a full working example:编辑:这是一个完整的工作示例:

#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;
}

That prints:那打印:

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

Let's dissect str_split() , shall we?让我们剖析str_split() ,好吗?

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

Our first error.我们的第一个错误。 You can't have zero-length arrays.你不能有零长度的数组。 Also, you use the array later, so even if you could have zero-length arrays, you couldn't index into them.此外,您稍后会使用该数组,因此即使您可以拥有零长度数组,您也无法对它们进行索引。

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

Next error.下一个错误。 str is too small to hold base , since strlen() doesn't count the null-terminator. str太小而无法容纳base ,因为strlen()不计算空终止符。

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

Misuse of result . result误用。

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

Remember this, split has enough space for counter char * s...请记住这一点, split有足够的空间用于counter char * s...

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

Mixed up strlen() and sizeof() .混合strlen()sizeof()

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

Useless.无用。 If somestring[strlen(somestring)] wasn't already '\\0' , it wouldn't be strlen(somestring) .如果somestring[strlen(somestring)]还不是'\\0' ,它就不会是strlen(somestring)

        split[i] = result[i];

This leaks the memory allocated for split[i] and keeps a pointer to str , which goes out of scope when the function returns.这会泄漏为split[i]分配的内存并保留一个指向str的指针,当函数返回时该指针超出范围。 Replace with strcpy() .替换为strcpy()

    }
    split[counter] = 0;

Did you remember how much space split had?你还记得split了多少空间吗?

    return split;
}

You don't know what's going to happen to the passed-in value of name .您不知道传入的name值会发生什么。 If it was allocated on the stack, it will be overwritten.如果它是在堆栈上分配的,它将被覆盖。 Use a strcpy when assigning to v.name and you'll be safe.分配给v.name时使用 strcpy 并且您会安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM