首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >意外痕迹陷阱

意外痕迹陷阱
EN

Stack Overflow用户
提问于 2022-01-13 14:28:52
回答 1查看 663关注 0票数 0

我有以下代码:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define MAX_FIL 15
#define MAX_COL 15
#define MAX 15*15


int frase_a_taula(char frase[], char taula[MAX_FIL][MAX_COL]) {
    int i, j, k = 0, l, res = 0, final = 0;
    for (i = 0; !final; i++) {
        l = 0;
        for (j = i; frase[j] != ' ' && frase[j] != '.'; j++) {
            taula[k][l] = frase[j];
            l++;
        }
        taula[k][l] = '\0';
        if (frase[j] == '.') final = 1;
        i = j;
        k++;
        res++;
    }
    return res;
}


void mescla_string_taula(char taula[MAX_FIL][MAX_COL], int n_filas, int coeficient) {
    int n_mescles = 0, i, ind1, ind2;
    if (coeficient == 2) {
        n_mescles = n_filas / 2;
    }
    else if (coeficient == 1) {
        n_mescles = n_filas / 4;
    }

    srand(time(NULL));
    for (i = 0; i < n_mescles; i++) {
        ind1 = rand() % n_filas;
        ind2 = rand() % n_filas;
        char *temp = (char *)malloc((strlen(taula[ind1]) + 1) * sizeof(char));
        strcpy(temp, taula[ind1]);
        strcpy(taula[ind1], taula[ind2]);
        strcpy(taula[ind2], temp);
        free(temp);
    }

}

void alenteix_i_mescla_frase(char frase[MAX], char frase_lenta[MAX], 
                             int velocitat, int coeficient) {
    char taula[MAX_FIL][MAX_COL];
    int i, j, len_frase_lenta;
    int n_paraules = frase_a_taula(frase, taula);
    mescla_string_taula(taula, n_paraules, coeficient);

    
    strcpy(frase_lenta, taula[0]);

    len_frase_lenta = strlen(frase_lenta);
    for (i = 1; i < n_paraules; i++) {
        if (velocitat == 1) {
            if (i % 2 == 0) {
                frase_lenta[len_frase_lenta] = '.';
                frase_lenta[len_frase_lenta + 1] = '.';
                frase_lenta[len_frase_lenta + 2] = '.';
                len_frase_lenta += 3;
                for (j = 0; j < strlen(taula[i]); j++) {
                    frase_lenta[len_frase_lenta] = taula[i][j];
                    len_frase_lenta++;
                }
            }
            else {
                frase_lenta[len_frase_lenta] = ' ';
                len_frase_lenta++;
                for (j = 0; j < strlen(taula[i]); j++) {
                    frase_lenta[len_frase_lenta] = taula[i][j];
                    len_frase_lenta++;
                }
            }
        }
        else if (velocitat == 2) {
            frase_lenta[len_frase_lenta] = '.';
            frase_lenta[len_frase_lenta + 1] = '.';
            frase_lenta[len_frase_lenta + 2] = '.';
            len_frase_lenta += 3;
            for (j = 0; j < strlen(taula[i]); j++) {
                frase_lenta[len_frase_lenta] = taula[i][j];
                len_frase_lenta++;
            }
        }
    }
    frase_lenta[len_frase_lenta] = '.';
    frase_lenta[len_frase_lenta+1] = '\0';
    
}


int main() {
    printf("Introdueix nom del fitxer: ");
    char path[MAX];
    scanf("%s", path);
    printf("Introdueix velocitat de parla: ");
    int velocitat;
    scanf("%d", &velocitat);
    printf("Introdueix el coeficient de yodificacio: ");
    int coef;
    scanf("%d", &coef);
    FILE* f = fopen(path, "r");
    if (f == NULL) {
        printf("Fitxer no trobat!");
    }
    else {
        char line[MAX], frase_yodificada[MAX];
        while (fgets(line, MAX, f) != NULL) {
            alenteix_i_mescla_frase(line, frase_yodificada, velocitat, coef);
            printf("%s\n", frase_yodificada);
        }
        printf("De processar...ha acabat, el fitxer\n");
    }
    return 0;
}

和文件yodatest.txt

代码语言:javascript
复制
may the force be with you.
may the force be with you every day of your life.
avui fa un dia molt bonic.
hola.
si entrenes molt i ets perseverant arribaras lluny i tindras molts poders.
un dia em comprare una moto i anire volant fins a l'estrella de la mort.
no hi ha dia que no m'agradi mirar les estrelles de nit.

Ubuntu wsl中在Windows下编译和执行此代码时,我没有任何错误。但是,当我编译代码并在MacOs中执行它时,我得到了输出:

[1] 60023 trace trap ./main.exe

有时它正确执行,有时没有执行,但是我尝试在Ubuntu下执行了几次,并且总是得到正确的答案。此外,注释mescla_string_taula似乎有效,但我也不能肯定,因为错误的本质。基本上,这个函数只是改组矩阵。知道为什么会发生这种事吗?

一个正确的例子是:

代码语言:javascript
复制
Introdueix nom del fitxer: yodatest.txt
Introdueix velocitat de parla: 1
Introdueix el coeficient de yodificacio: 1
may the...force you...with be.
with the...force be...may of...every day...you your...life.
avui fa...un bonic...molt dia.
hola.
si molts...molt i...ets poders...arribaras lluny...i perseverant...entrenes tindras.
volant anire...em comprare...una fins...i dia...un moto...a l'estrella...de la...mort.
no de...ha dia...que nit...m'agradi mirar...les no...hi estrelles.
De processar...ha acabat, el fitxer
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-19 00:26:58

首先,我将展示如何使用调试器查找问题,因为这是一种不太为人所知的技术。

首先,我将提供的源代码复制并粘贴到文件yoda.c中,并将提供的测试输入复制到文件yodatest.txt中。(这就是为什么我们总是要求以文本形式提供源代码和测试数据,而不是以图像或其他任何形式提供。从我的web浏览器复制和粘贴东西到我的C编译环境只需要几秒钟,然后我就开始运行了。)

我编译了yoda.c并运行了它,得到了一个非常类似的错误:

代码语言:javascript
复制
Abort trap: 6

这很有希望。(有时很难或不可能复制一个bug,从而使它更难诊断。)

接下来,我编译用于调试:

代码语言:javascript
复制
cc -g yoda.c

并在调试器下运行程序:

代码语言:javascript
复制
$ lldb a.out
(lldb) target create "a.out"
Current executable set to 'a.out' (x86_64).
(lldb) run

输入"run“运行程序。但是现在,当它崩溃时,我从调试器获得了相当多的输出:

代码语言:javascript
复制
2022-01-18 19:21:07.871139-0500 a.out[34597:99984533] detected source and destination buffer overlap
Process 34597 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff57022e3e libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
->  0x7fff57022e3e <+10>: jae    0x7fff57022e48            ; <+20>
    0x7fff57022e40 <+12>: movq   %rax, %rdi
    0x7fff57022e43 <+15>: jmp    0x7fff5701a0b8            ; cerror_nocancel
    0x7fff57022e48 <+20>: retq   
Target 0: (a.out) stopped.

我可以输入"bt“以获得堆栈回溯:

代码语言:javascript
复制
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff57022e3e libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff57161150 libsystem_pthread.dylib`pthread_kill + 333
    frame #2: 0x00007fff56f7f312 libsystem_c.dylib`abort + 127
    frame #3: 0x00007fff56f7f485 libsystem_c.dylib`abort_report_np + 177
    frame #4: 0x00007fff56fa3c2d libsystem_c.dylib`__chk_fail + 48
    frame #5: 0x00007fff56fa3c3d libsystem_c.dylib`__chk_fail_overlap + 16
    frame #6: 0x00007fff56fa3c6e libsystem_c.dylib`__chk_overlap + 49
    frame #7: 0x00007fff56fa3e39 libsystem_c.dylib`__strcpy_chk + 64
    frame #8: 0x000000010000084e a.out`mescla_string_taula(taula=0x00007ffeefbff550, n_filas=12, coeficient=1) at yoda.c:44
    frame #9: 0x0000000100000907 a.out`alenteix_i_mescla_frase(frase="si entrenes molt i ets perseverant arribaras lluny i tindras molts poders.\n", frase_lenta="hola.", velocitat=1, coeficient=1) at yoda.c:56
    frame #10: 0x0000000100000dd2 a.out`main at yoda.c:117
    frame #11: 0x00007fff56ed3115 libdyld.dylib`start + 1

这告诉我,对strcpy的冒犯调用是yoda.c第44行的调用。(这很方便,因为程序中有四个对strcpy的调用,否则我可能不知道是哪个调用导致了问题。)

显然这条线

代码语言:javascript
复制
strcpy(taula[ind1], taula[ind2]);

mescla_string_taula()中,可以将字符串复制到自身之上。在这种情况下,strcpy没有被定义为正确的行为。

一个被定义为在重叠情况下正常工作的函数是memmove。我用

代码语言:javascript
复制
memmove(taula[ind1], taula[ind2], strlen(taula[ind2])+1);

现在这个计划似乎奏效了。

请注意,我没有更深入地分析问题,也没有检查其他问题,更不用说证明程序对所有输入都是正确的。(在评论中,鲁德·赫尔德曼发现了其他一些可疑代码。)但是在我的机器上,修改后的程序现在确实为这个测试用例生成了所需的输出。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70698277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档