簡體   English   中英

將 char * 轉換為 char ** 時出現分段錯誤

[英]Segmentation fault when converting char * to char **

我正在嘗試將句子(char *)拆分為單詞數組(char **)。 問題是我的函數有時不會返回有效的字符 **。

char **get_words(char *buffer, char delimiter)
{
    char **words = malloc(sizeof(char *) * 4096);
    for (int i = 0; i < 4096; i++)
        words[i] = malloc(sizeof(char) * 4096);
    int word_count = 0;
    int l = 0;
    for (int i = 0; buffer[i] != '\0' && buffer[i]  != '\n'; i++, l++) {
        if (buffer[i] == delimiter) {
            words[word_count][l] = '\0';
            word_count++;
            l = -1;
        }
        else
            words[word_count][l] = buffer[i];
    }
    words[word_count][l] = '\0';
    return (words);
}

我首先像這樣使用它:

char *buffer = malloc(sizeof(char) * 50);
buffer = "/login test\n";
char **words = get_words(buffer, ' ');
printf("Words[0] = %s", words[0]);

它工作正常。

但是,當我這樣做時:

char **reply = get_words("502 Command doesn't exist.\n", ' ')

如果沒有分段錯誤,我什至無法打印回復[0][0](見下文)。 此外,我嘗試使用 valgrind 進行調試,但是當我使用它時,程序不會崩潰並且一切正常,所以我找不到問題所在。

printf("Reply[0][0] = %d\n", reply[0][0]);

printf("Reply[0][0] = %c\n", reply[0][0]);

編輯:這是一個可復制的例子。

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>

char **get_words(char *buffer, char delimiter)
{
    printf("buffer = %s\n", buffer);
    char **words = malloc(sizeof(char *) * 100);
    if (words == NULL) {
        printf("Malloc Error\n");
        exit(84);
    }
    for (int i = 0; i < 100; i++) {
        words[i] = malloc(sizeof(char) * 100);
        if (words[i] == NULL) {
            printf("Malloc Error\n");
            exit(84);
        }
    }
    int word_count = 0;
    int l = 0;
    for (int i = 0; buffer[i] != '\0' && buffer[i]  != '\n'; i++, l++) {
        if (buffer[i] == delimiter) {
            words[word_count][l] = '\0';
            word_count++;
            l = -1;
        }
        else
            words[word_count][l] = buffer[i];
    }
    words[word_count][l] = '\0';
    return (words);
}

int main()
{
    char *buffer = malloc(sizeof(char) * 100);
    buffer = "hello world !\n";
    char **words = get_words(buffer, ' ');
    printf("words[0]= %s\n", words[0]);
    free (buffer);
    char **reply = get_words("Second call\n", ' ');
    printf("reply[0] = %s\n", reply[0]);
}

如果您在學習編程方面需要幫助,可以嘗試使用靜態分析器。 這是一個執行代碼審查並發現可疑代碼片段的程序。 靜態分析器不能代替隊友執行的代碼審查。 然而,分析器補充了代碼審查並幫助在最早階段發現許多錯誤。

讓我們為問題所附的代碼示例運行PVS-Studio 分析器的在線版本。 第一個有趣且重要的警告是以下警告: V1031未聲明malloc函數。 將數據傳入或傳出此函數可能會受到影響。

在沒有聲明malloc函數的情況下,程序以一種奇怪的方式運行。 根據 C 語言,如果未聲明函數,則返回int 但實際上,它是一個指針。 你可以在這里找到為什么這是危險的 讓我們通過添加#include <stdlib.h>來解決這個問題。

現在分析器發出另一個警告——我們遇到了一個更嚴重的問題: 43:1:注意:V773 'buffer' 指針被賦值兩次,但沒有釋放內存。 內存泄漏是可能的。

問題出在以下代碼片段中:

char *buffer = malloc(sizeof(char) * 100);
buffer = "hello world !\n";
....
free (buffer);

指針值被覆蓋。 要將字符串復制到緩沖區,程序員應該使用特殊函數,例如strcpy 讓我們解決這個問題。

這是固定代碼

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <assert.h>
#include <stdlib.h>

char **get_words(char *buffer, char delimiter)
{
    printf("buffer = %s\n", buffer);
    char **words = malloc(sizeof(char *) * 100);
    if (words == NULL) {
        printf("Malloc Error\n");
        exit(84);
    }
    for (int i = 0; i < 100; i++) {
        words[i] = malloc(sizeof(char) * 100);
        if (words[i] == NULL) {
            printf("Malloc Error\n");
            exit(84);
        }
    }
    int word_count = 0;
    int l = 0;
    for (int i = 0; buffer[i] != '\0' && buffer[i]  != '\n'; i++, l++) {
        if (buffer[i] == delimiter) {
            words[word_count][l] = '\0';
            word_count++;
            l = -1;
        }
        else
            words[word_count][l] = buffer[i];
    }
    words[word_count][l] = '\0';
    return (words);
}

int main()
{
    char *buffer = malloc(sizeof(char) * 100);
    if (buffer == NULL)
        exit(84);
    strcpy(buffer, "hello world !\n");
    char **words = get_words(buffer, ' ');
    printf("words[0]= %s\n", words[0]);
    free (buffer);
    char **reply = get_words("Second call\n", ' ');
    printf("reply[0] = %s\n", reply[0]);
}

我不能說這段代碼是完美和安全的,但它可以運行。 因此,使用靜態分析器查找錯誤,您可以改進您的學習過程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM