尝试将字符串分配给结构内的字符串变量时出错
Error when trying to assign a string into a string variable inside a struct
我正在编写词法分析器软件,但是当我尝试将字符串分配给结构内的字符串变量时遇到问题。
--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] == '[=10=]')
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
我试过用token[toknum].string = string;
替换strcpy(token[toknum].string, string);
,但结果是一样的。
有什么办法可以避免这个错误吗?
您正在使用未初始化的变量:
struct Token* token;
这只定义了一个指针变量,没有赋值任何有效内容。这意味着 indetermioned 中的内容和读取此变量的内容会导致未定义的行为。
此外,此变量未指向有效地址。通过 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];
会保留内存,但您不能 return 函数末尾的地址,因为该对象的生命周期将同时结束,您可能无法在 returning 之后访问它。
同样的问题出现在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
都有效,那么您使用 token[toknum].string = string;
的尝试将有效。
同篇还有一个问题:
for (i += 1; input[i] != ' '; i++) {
string[i] = input[i];
}
strcpy(token[toknum].string, string); // << strcpy expects a nul-terminated string
你没有正确终止你的字符串。在这种情况下,strcpy
将愉快地遍历您的内存,超出内存分配的边界,直到意外找到终止 [=24=]
字节。
并且...如果 input
不包含另一个 space 字符会怎样?这个循环最终会到达 input
的终止 0
并继续...
还有两个原因等着你。
这只是我在 tokenizer
中第一眼看到的内容。
在函数 PrintToken
中,您还有另一个问题:
是什么让你想到,你可以打印 token
的 5 个元素?您永远不会为 5 个元素保留内存,即使您这样做了,您也不会将多余的元素初始化为包含一些空字符串。
我正在编写词法分析器软件,但是当我尝试将字符串分配给结构内的字符串变量时遇到问题。
--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] == '[=10=]')
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
我试过用token[toknum].string = string;
替换strcpy(token[toknum].string, string);
,但结果是一样的。
有什么办法可以避免这个错误吗?
您正在使用未初始化的变量:
struct Token* token;
这只定义了一个指针变量,没有赋值任何有效内容。这意味着 indetermioned 中的内容和读取此变量的内容会导致未定义的行为。
此外,此变量未指向有效地址。通过 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];
会保留内存,但您不能 return 函数末尾的地址,因为该对象的生命周期将同时结束,您可能无法在 returning 之后访问它。
同样的问题出现在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
都有效,那么您使用 token[toknum].string = string;
的尝试将有效。
同篇还有一个问题:
for (i += 1; input[i] != ' '; i++) {
string[i] = input[i];
}
strcpy(token[toknum].string, string); // << strcpy expects a nul-terminated string
你没有正确终止你的字符串。在这种情况下,strcpy
将愉快地遍历您的内存,超出内存分配的边界,直到意外找到终止 [=24=]
字节。
并且...如果 input
不包含另一个 space 字符会怎样?这个循环最终会到达 input
的终止 0
并继续...
还有两个原因等着你。
这只是我在 tokenizer
中第一眼看到的内容。
在函数 PrintToken
中,您还有另一个问题:
是什么让你想到,你可以打印 token
的 5 个元素?您永远不会为 5 个元素保留内存,即使您这样做了,您也不会将多余的元素初始化为包含一些空字符串。