c - 指针的内容在使用后消失

时间:2015-11-30 10:58:18

标签: c pointers

我有这段代码,其中complexp是指向struct的指针,表示复数。第一个printf命令工作正常,并打印complexp个内容。但是,第二个printf无法正常工作并打印0两次(这是不正确的)。

这两行之间没有代码。

int main()
    {
        ComplexP  complexp =  (ComplexP) malloc(sizeof(ComplexP));
        complexp = fromCharFunc(s);

        printf("complexp: real: %f, imaginary: %f\n", complexp->real, complexp->imaginary);

         printf("1complexp: real: %f, imaginary: %f\n", complexp->real, complexp->imaginary);

    return 0;
    }
 typedef struct Complex {
   double real;
   double imaginary;
 } Complex;

typedef struct Complex* ComplexP;
ComplexP fromCharFunc(char * s)
{
    if(s == NULL)
    {
        return NULL;
    }


char* sreal;
char* simaginary;
double real;
double imaginary;

char str [DEFAULT_SIZE];

strcpy(str, s);
sreal = strtok(str, REALL_PART_DELIMITER);

simaginary = strtok(NULL, IMAGINARY_PART_DELIMITER);

int len1 = strlen(sreal) + strlen(simaginary);
int len2 = strlen(s) - strlen(IMAGINARY_PART_DELIMITER);

int diff = len1 == len2 ? 0 : 1;


if(diff)
{
    return NULL;
}


if(verifyIsNumber(sreal))
{
    real = atof(sreal);
}
else
{
    return NULL;
}

if(verifyIsNumber(simaginary))
{
    imaginary = atof(simaginary);
}
else
{
    return NULL;
}

Complex complex = {real, imaginary};
ComplexP complexp = &complex;

return complexp;

}
/**
 * @brief determines whether a string represents a number
 * @param char *s poiter to a string
 * #retrun 0 if not a number, 1 if is a number
 */
int verifyIsNumber(char *s)
{
char c;
int i = 0;
while( *(s+i) != '\0')
{
    c = *(s+i);
    if ((c >= MIN_DIGIT && c <= MAX_DIGIT) || c == POINT || c == MINUS)
        i++;
    else
    {
        return 0;
    }
}

return 1;

}

3 个答案:

答案 0 :(得分:1)

对发布的完整代码的响应

我能够重现你的问题。问题来自以下几点:

ComplexP fromCharFunc(char * s)
{
    /* ... */
    Complex complex = {real, imaginary};
    ComplexP complexp = &complex;

    return complexp;
}

这里,complex是一个堆栈变量,这意味着一旦函数返回它就会超出范围。第一次打印正确答案的事实是半巧合,可能是基于数据尚未被覆盖的事实。这是未定义的行为。如果您需要引用生存,请使用calloc()malloc()分配您的内存,并且不要忘记稍后free()。您可以在我的示例中看到calloc()正在工作,尽管在简短示例中我省略了free()调用。

工作示例

我尝试了你的代码(在把它变成一个完整的工作示例之后,这会有所帮助!),它可以工作:

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

typedef struct Complex {
    double real;
    double imaginary;
} Complex;

typedef struct Complex* ComplexP;

int main(int argc, char **argv) {
    ComplexP complexp = calloc(sizeof(Complex), 1);

    complexp->real = 42;
    complexp->imaginary = 100.5;

    printf("complexp: real: %f, imaginary: %f\n", complexp->real,
                                                  complexp->imaginary);

    printf("complexp: real: %f, imaginary: %f\n", complexp->real,
                                                  complexp->imaginary);

    return 0;
}

因此,代码中必须存在未显示的内容。我建议从一个较小的示例开始,像我一样,然后重新添加功能,直到找到问题为止。

C99 complex类型

另外,如果你不知道,C99 already includes a standard definition for complex numbers。您可以查看<complex.h>,看看它是否符合您的需求。

答案 1 :(得分:1)

您正在返回指向局部变量的指针。在范围的末尾删除该变量。您应该考虑返回Complex变量而不是ComplexP

ComplexP fromCharFunc(char * s)
{

    // ...

    // This variable is deleted after the function ends
    Complex complex = {real, imaginary};

    // After deletion, this pointer points to invalid memory
    ComplexP complexp = &complex;

    return complexp;
}

您的第一个printf调用有效,因为complex中的值仍然恰好位于指针所指向的内存位置。这是未定义的行为。使用不同的编译器或不同的系统,可能会导致两个printf命令失败,或者两者都成功。

如果您想返回ComplexP,则应使用malloc保留记忆。

ComplexP fromCharFunc(char * s)
{

    // ...

    // Create a temporary variable
    Complex complex = {real, imaginary};

    // Reserve memory for your return variable
    ComplexP complexp = malloc(sizeof(Complex));

    // Copy your temporary variable to the reserved memory location
    *complexp = complex;

    return complexp;
}

答案 2 :(得分:0)

您可以使用gdb调试程序。在到达第二个printf语句之前,必须释放指针。只有使用gdb才能轻松解决此问题。

要跟踪问题,必须在编译时在程序中启用调试符号。您可以通过提供-g标志来完成此操作。