c strcat with pointers

时间:2010-11-27 20:53:47

标签: c pointers memory-management

我想用C编写这个示例函数(请不要判断那段代码的目的,它只用于学习C)。它应该使用动态分配内存来消耗更多的内存,而不是必需的。

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

char ** LCS ( char * s1, char * s2 ) {
    int i, ii, myI;
    char ** commonSequence = (char**) malloc(1 * sizeof (char**));
    *commonSequence = NULL;

    int commonChars = 0;
    for (i = 0; i < (int)strlen(s1);i++) {
        for (ii = 0; ii < (int)strlen(s2); ii++) {
            if (s1[i] == s2[ii]) {
                commonChars++;
                if (commonChars > 1) {
                    commonSequence = (char**) realloc(commonSequence, (commonChars+1) * sizeof (char**));
                    strcat((char*)commonSequence, (const char *)s1[i]);
                }
                i++;
            }
        }
    }

    return commonSequence;
}

int main ( int argc, char * argv [] ) {
    char ** output = LCS((char*)"AATK", (char*)"AABC");

    printf("\n\nCommon: %s", *output);
    free(output);

    return 0;
}

上面的代码导致“分段错误”错误(可能是内存分配错误或类似的错误)。当我在Valgrind中运行时,它会输出:

==29381== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 3 from 3)
==29381==
==29381== 1 errors in context 1 of 1:
==29381== Invalid read of size 1
==29381==    at 0x4028A80: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-l                                                                                          inux.so)
==29381==    by 0x80485BA: LCS(char*, char*) (main.cpp:19)
==29381==    by 0x8048626: main (main.cpp:31)
==29381==  Address 0x41 is not stack'd, malloc'd or (recently) free'd

可能我没有正确使用 strcat 功能......但实际上我不知道该修复什么......

5 个答案:

答案 0 :(得分:2)

您正在将s1[i] char投射到无意义的const char *指针中:

strcat((char*)commonSequence, (const char *)s1[i]);

您还要将commonSequencechar **转换为char *,这将无效。你可能想要这样的东西:

strcat(*commonSequence, ((const char *)s1)[i]);

但是你为commonSequence分配内存的方式确实有问题。看起来你正在构建一个字符串列表,而不是自己分配字符串。

答案 1 :(得分:2)

您对malloc的使用是假的,但由于数字恰好正确,错误可能不会被捕获。这一行:

char ** commonSequence = (char**) malloc(1 * sizeof (char**));

应为:

char ** commonSequence = malloc(1 * sizeof (char*));

或者最好:

char ** commonSequence = malloc(1 * sizeof *commonSequence);

最终形式是最好的,因为如果您更改commonSequence的类型,它不需要任何更改。至于原始行的实际问题,您需要根据要指向的对象的大小进行分配,而不是指向它的指针的大小。在实践中,由于两者都是指针,它们在现代真实世界的机器上将具有相同的大小,但它仍然是一个严重的概念错误,当您将不正确的模式应用于非指针类型时,它可能会咬你。例如,这会导致内存损坏/未定义的行为:

struct foobar *foo = malloc(1 * sizeof (struct foobar *));

因为它只分配4或8个字节而不是结构的大小。

答案 2 :(得分:0)

 strcat((char*)commonSequence, (const char *)s1[i]);

strcat需要一个指针,你在(const char *)s1[i]做的是你正在访问该角色,然后将其作为指针给出。也就是说,不是strcat应该开始的地址,而是给它字符的值。

答案 3 :(得分:0)

您为指向字符串的指针分配内存,但不为字符串本身分配内存。 strcat()的第一个参数似乎应该是*commonSequence

答案 4 :(得分:0)

你需要传递s1 [i]的地址。简单地投射它不会使它成为有效的地址。同样将char **转换为char *将不会产生您期望的结果。您应取消引用它以访问存储在char **

中的char *指针
strcat( *commonSequence, &s1[i] );

也就是说,其余的代码看起来很可疑。我想知道你到底想要的是什么?但你明确要求我们不要质疑!