2

我遇到了动态数组和malloc. 我对C相当陌生,所以请原谅(并建议)任何新手错误。

问题是我创建了一个数组(在本例中为 input_string)并将其传递给func2. 然后在func2我做一个测试,打印出 input_string 的第一个元素。

这在 之前的第一个打印输出中按预期工作malloc,但在之后malloc它不打印任何内容。这对我来说似乎很奇怪,因为在 toprintf语句之间我对 input_string 什么都不做。

我假设我处理这些数组不正确,但我不确定。

这是有问题的代码片段:

更新

... // includes not in snippet

/* CONSTANTS */
#define LINE_LEN 80

/* Function declarations */
char* func1(void);
char* func2(int tl, char* input_string);

int main(void) {
    char* input_string;
    int tab_length;
    char* output_string;

    input_string = func1();
    output_string = func2(tl, input_string);

    return 0;
}

char* func1(void) {
    char cur_char;
    char* input_ptr;
    char input_string[LINE_LEN];
    while ((cur_char = getchar()) != '\n' && chars_read < 80) {
        // iterate and create the array here
    }
    input_ptr = &input_string[0]; /* set pointer to address of 0th index */
    return input_ptr;
}

char* func2(int tl, char* input_string) {
    int n = 0, output_idx = 0;
    char* output_ptr;
    printf("\nBefore malloc: %c ", *(input_string));
    output_ptr = malloc(tab_length * chars_read+1);
    if (output_ptr == NULL) {
            printf("Failed to allocate memory for output_ptr.\nExiting");
            exit(1);
    }
    printf("\nAfter malloc: %c ", *(input_string));
    ...
    return output_ptr;
}

Ps:任何未声明的变量都已在此代码段之外声明。

更新

感谢所有的回复和建议。这是非常赞赏。

4

2 回答 2

2

func1返回一个指向临时字符串的指针。你没有分配它。这将产生未定义的行为。

相反,您应该这样做:

char* func1(void) {
    char cur_char;
    char* input_ptr = (char*)malloc(LINE_LEN * sizeof(char));
    while ((cur_char = getchar()) != '\n' && chars_read < 80) {
        // iterate and create the array here
    }
    return input_ptr;
}

有趣的是,您确实使用了mallocinside func2

完成后,您需要调用free以释放内存。

int main(void) {
    char* input_string;
    int tab_length;
    char* output_string;

    input_string = func1();
    output_string = func2(tl, input_string);

    free(input_string);
    free(output_string);    

    return 0;
}
于 2012-09-14T03:52:51.013 回答
2

一个主要问题是您返回一个指向本地数组的指针:

char* func1(void)
{
    char cur_char;
    char* input_ptr;
    char input_string[LINE_LEN];
    while ((cur_char = getchar()) != '\n' && chars_read < 80) {
        // iterate and create the array here
    }
    input_ptr = &input_string[0]; /* set pointer to address of 0th index */
    return input_ptr;
}

您已设置input_ptr指向本地数组input_string(它的第零个元素),然后返回该指针。一旦函数返回,指针无效;该空间被重新用于其他目的。

如果您无论如何都没有收到编译器警告,则应该使用更多警告集进行编译(并且在您知道足够的 C 以知道为什么可以安全地忽略警告之前,您不应该忽略警告)。我-Wall -Wextra几乎总是使用,而且-Wall基本上总是使用。


正如Morpfh指出的那样,GCC(在 Mac OS X 10.7.4 上测试的 4.7.1)不会就返回指针发出警告,因此在没有编译器帮助的情况下,您必须注意这一点。(如果您将返回更改为return input_string;or return &input_string[0];,那么编译器确实会给您一个有用的警告。)

另外,在将代码转换为可编译单元时,我注意到您没有处理 EOF,而是将结果分配getchar()给 a char; 你不应该因为它返回一个int(参见'fgetc()检查EOF'以及许多其他问题以了解有关此问题的另一个讨论)。您还需要确保您的字符串以空值结尾。您还应该避免重复常量,因此不要在条件中使用 80,而是使用 LINE_LEN (或者,甚至更好,sizeof(input_string)-1)。而且您必须注意一个接一个的缓冲区溢出。所以,我的可编译版本func1()是:

#include <stdio.h>
#include <stdlib.h>
#define LINE_LEN 80
extern char *func1(void);
char *func1(void)
{
    int cur_char;
    char *input_ptr;
    int chars_read = 0;
    char input_string[LINE_LEN+1];

    while ((cur_char = getchar()) != EOF && cur_char != '\n' && chars_read < LINE_LEN)
        input_string[chars_read++] = cur_char;

    input_string[chars_read] = '\0';
    input_ptr = &input_string[0]; /* set pointer to address of 0th index */
    return input_ptr;
}

这仍然是损坏的代码,因为它返回本地指针。

于 2012-09-14T03:54:56.740 回答