用于创建轮换的代码 Table 在 GDB 在线工作,但在 Code::Blocks 中不工作

Code for creating a Rotation Table working in GDB online, but not working in Code::Blocks

首先我想说我绝对不是 C 编程方面的专家,而且我已经有一段时间没有这样做了。

但我的任务是用 C 编写代码来解决有关组合数学的问题。

基本任务是,给定任何单词,构造一个正方形 table,其中包含一个单词所有可能的右移。第一步之后还有很多东西,但这是最重要的,也是给我带来麻烦的。

实际例子: 如果单词是“ababa”,“二维数组”应该包含:

  1. 阿巴巴
  2. aabab
  3. 咩咩
  4. 阿巴
  5. 粑粑

因为这个二维数组的大小总是长度 * 长度(所以如果单词的长度为 5,table 将是 5x5)我认为要做的事情是:

  1. 调用将长度作为参数传递的函数
  2. 使用 malloc 创建一个 char**,使其大小正确
  3. return 表示 char**
  4. 调用另一个函数用字符串填充它

我想出了以下代码,但实际上它在 GDB 在线版中完美运行,return在 Code::Blocks 中是一个错误。错误是:进程终止,状态为 -1073741819

令我困惑的是,当我尝试调试它时,Code::Blocks 中的代码确实有效。 这是分配数组的函数:

char** returnTable(int length){
char** rotationTable = malloc(length*sizeof(char));
char* values = calloc((length+1)*(length+1), sizeof(char));

for(int i=0; i<length; i++){
        rotationTable[i] = values + i*(length+1);
        rotationTable[i][0] = '[=12=]';
}
return rotationTable;}

这是用正确的词填充结构的函数:

void orderedConjugacyClass(char** table, char* word, int length){
    //first word copied in the rotationTable
    table[0] = strdup(word);
    //let's start from the second row
    int j = 1;
    //p on the last char of the word
    char* p = &table[j-1][length-1];
    //q on the first 
    char* q = &table[j-1][0];
    //buffer string, +1 for terminating character
    char buffer[length+1];
    buffer[0] = '[=13=]';

    while(j < length){
        strncat(buffer, p, 1);
        strncat(buffer, q, length-1);
        buffer[length] = '[=13=]';
        table[j] = strdup(buffer);
        p = &table[j][length-1];
        q = &table[j][0];
        //to cancel and reuse the buffer for next iteration
        buffer[0]='[=13=]';
        j++;
    }
}

主要是我简单地调用了这两个函数。如果我只限于此,则代码(显然)没有问题。但是每当我尝试访问 table 的内容并用 printf 显示它时,就会出现问题并且 GDB 在线和 CodeBlocks 之间的输出“不同”:

 int length = strlen(argv[1]);
        char** rotationTable = returnTable(length);
        orderedConjugacyClass(rotationTable, argv[1], length);
        
        for(int j=0; j<length; j++)
                printf("%s\n", rotationTable[j]);
        
        for(int i=0; i<length; i++)
            free(rotationTable[i]);
        free(rotationTable);
        return 0;

其他详细信息:我正在使用 Windows,MinGW 编译器。

感谢您的帮助和理解。

不要这样做:

SomeType something = malloc(length*sizeof(SomeType));

这样做:

SomeType something = malloc(length*sizeof(*something));

只有当 SomeType 的两种用法相同时,第一个才是正确的,并且很容易使它们不同,特别是如果您在程序中的某个点更改 SomeType发展。

在这种情况下,您写了

char** rotationTable = malloc(length*sizeof(char));

这里的元素类型是char*,但是你在sizeof中使用了char,导致你分配的太少了space。

如果你写了

char** rotationTable = malloc(length*sizeof(*rotationTable));

你不会有那个问题。


另请注意,您正在预先分配 rotationTable 的元素,然后将预先分配的数组替换为其他数组。最初分配的指针丢失了,所以你永远不会释放它们,所以你有内存泄漏。我不明白 returnTable 的意义。只需 orderedConjugacyClass 创建并 return 数组即可。


最后,这很愚蠢。

        strncat(buffer, p, 1);
        strncat(buffer, q, length-1);
        buffer[length] = '[=14=]';

strncat 必须扫描目的地以找到其终点。但你知道尽头在哪里。所以花在扫描字符串上的周期是完全没有意义的。

buffer[0] = p[0];
memcpy(buffer+1, q, length-1);
buffer[length] = '[=15=]';

另一方面,pq 也有点毫无意义,因为您可以直接从原始单词复制。实际上,您也可以摆脱 buffer

/* Production code should check if malloc succeeded */
char** conjTable(const char* word) {
    size_t len = strlen(word);
    char** table = malloc(len * sizeof(*table));
    for (size_t i = 0; i < len; ++i) {
        table[i] = malloc(len + 1);
        memcpy(table[i], word + len - i, i);
        memcpy(table[i] + i, word, len - i);
        table[i][len] = '[=16=]';
    }
    return table;
}