我正在撰寫一個詞法分析器軟體,但是當我嘗試將一個字串分配給結構內的字串變數時遇到了問題。
--common.h--
#define TEST printf("--TEST--\n")
struct Token {
char* ID;
char* string; // String variable
};
struct Token* tokenizer(char* input);
void PrintToken(struct Token* token);
--lexer.c--
#include <stdio.h>
#include <string.h>
#include "common.h"
struct Token* tokenizer(char* input)
{
struct Token* token;
int toknum = 0;
int i = -1;
while (1) {
char* string;
for (i = 1; input[i] != ' '; i ) {
string[i] = input[i];
}
strcpy(token[toknum].string, string); // The problem is here.
if (input[i] == '\n' || input[i] == '\0')
break;
toknum ;
}
return token;
}
void PrintToken(struct Token* token)
{
for (int i = 0; i < 5; i ) {
printf("%s\n", token[i].string);
}
}
--main.c--
#include <stdio.h>
#include "common.h"
int main()
{
char* input = "Hello there";
struct Token* token = tokenizer(input);
PrintToken(token);
return 0;
}
在我編譯上面的程式gcc main.c lexer.c -o final.o并運行 final.o 后,我得到一個錯誤,它說:
Segmentation fault
我試過,以取代strcpy(token[toknum].string, string);與token[toknum].string = string;,但結果是一樣的。
有什么辦法可以避免這個錯誤嗎?
uj5u.com熱心網友回復:
您正在使用未初始化的變數:
struct Token* token;
這僅定義了一個指標變數,但不分配任何有效內容。這意味著不確定的內容和讀取此變數的內容會導致未定義的行為。
此外,此變數未指向有效地址。通過寫入“隨機”地址strcpy也會導致未定義的行為。
您必須為此分配動態記憶體:
struct Token *token = malloc(sizeof(*token));
// don't forget error handling
然后當你想要更多條目時,擴大記憶體:
struct Token *temp = realloc(token, (toknum 1)*sizeof (*token));
if (NULL != temp)
token = temp;
else
// error handling
只需使用這樣的陣列:
struct Token token[x];
將保留記憶體,但您不能在函式結束時回傳該地址,因為該物件的生命周期將同時結束,并且您可能無法在回傳后訪問它。
同樣的問題出現在string:
char* string;
for (i = 1; input[i] != ' '; i ) {
string[i] = input[i]; // <<< string is uninitialized, does not point to valid memory.
}
您不為字串提供任何記憶體。在這里,您可以使用本地陣列來保存字串。
同樣的問題也與token[toknum].string.
您的結構僅包含指標。同樣,您需要保留記憶體。要么再次使用動態記憶體分配,要么創建token.string一個固定長度的陣列。
您嘗試使用token[toknum].string = string;會作業,如果token[toknum]和string兩者都是有效的。
同一篇文章中還有另一個問題:
for (i = 1; input[i] != ' '; i ) {
string[i] = input[i];
}
strcpy(token[toknum].string, string); // << strcpy expects a nul-terminated string
您沒有正確終止您的字串。在這種情況下,strcpy將愉快地遍歷記憶體分配范圍之外的記憶體方式,直到意外找到終止\0位元組。
而且...如果input不包含另一個空格字符會發生什么?這個回圈將eventuall命中終止0的input,只是繼續...
這是等待您的意外行為的另外兩個原因。
這只是我tokenizer第一眼看到的。
在函式中,PrintToken您還有另一個問題:是什么讓您想到,您可以列印 5 個元素token?你永遠不會為 5 個元素保留記憶體,即使你這樣做了,你也不會初始化多余的元素以包含一些空字串。
uj5u.com熱心網友回復:
我不認為問題出在 strcpy 上,而出在tokenizer功能上。
行struct Token* token;是危險的,因為您正在初始化陣列,但不要為其分配記憶體。struct Token token[5]如果您的陣列具有固定數量的元素,請嘗試使用,或相應地使用malloc函式。
此外,同樣的問題是 char *string
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/378637.html
