我正在开发一个函数,它必须采用动态char数组,在空格中分隔它,并将每个单词放在char数组的数组中。这是代码:
char** parse_cmdline(const char *cmdline)
{
char** arguments = (char**)malloc(sizeof(char));
char* buffer;
int lineCount = 0, strCount = 0, argCount = 0;
int spaceBegin = 0;
while((cmdline[lineCount] != '\n'))
{
if(cmdline[lineCount] == ' ')
{
argCount++;
arguments[argCount] = (char*)malloc(sizeof(char));
strCount = 0;
}
else
{
buffer = realloc(arguments[argCount], strCount + 1);
arguments[argCount] = buffer;
arguments[argCount][strCount] = cmdline[lineCount];
strCount++;
}
lineCount++;
}
arguments[argCount] = '\0';
free(buffer);
return arguments;
}
问题是在某个地方我遇到了Segmentation故障而且我并不知道在哪里。 此外,该函数的当前版本假定字符串不以空格开头,即下一个版本,我可以处理,但我找不到seg的原因。故障
答案 0 :(得分:1)
此代码肯定不是您的意图:
char** arguments = (char**)malloc(sizeof(char));
它为一个char
分配足够大的内存块,并设置类型char **
(arguments
)的变量以指向它。但是,即使您只想在arguments
中为单个char *
留出足够的空间,您分配的内容还不够(无论如何,您可能不会遇到任何C系统)。多指针肯定不够长。
假设指针确实比C系统上的单个char
更宽,那么一旦解引用arguments
,程序就会调用未定义的行为。分段错误是更可能的结果之一。
最简单的方法可能是扫描输入字符串两次:一次计算单个参数的数量,这样就可以为指针分配足够的空间,并再次创建单个参数字符串并记录指向他们在你的阵列中。
另请注意,返回值不包含有关分配了多少空间的任何可访问信息,或者因此提取了多少参数字符串。解决此类问题的常用方法是为一个额外的指针分配空间,并将最后一个指针设置为NULL
作为标记。这与使用null char
标记C字符串的结尾非常相似,但不一样。
已编辑添加:
arguments
所需的分配更像是这样:
arguments = malloc(sizeof(*arguments) * (argument_count + 1));
也就是说,为一个对象分配空间而不是参数,每个对象的大小与arguments
指向的对象的大小相同。 arguments
不会访问sizeof
的值,因此在此时它不确定无关紧要。
已编辑添加:
最后的free()
电话也存在问题:
free(buffer);
此时,变量buffer
指向与arguments
的最后一个元素指向(或意图指向)的相同分配块。如果你释放它,那么所有指向该内存的指针都会失效,包括你要返回给调用者的指针。此时您不需要释放buffer
,而不需要在任何其他分配后释放它。
答案 1 :(得分:1)
这可能是您遇到分段错误的原因:
在char** arguments = (char**)malloc(sizeof(char));
中,您使用了malloc (sizeof (char))
,这只为一个字节分配空间(一个char
有足够的空间)。这不足以在char*
中保留一个arguments
。
但即使它在某个系统中,所以arguments[argCount]
只读取argCount = 0
的已分配内存。对于argCount
的其他值,数组索引超出范围 - 导致分段错误。
例如,如果您的输入字符串是这样的 - "Hi. How are you doing?"
,那么在到达4 ' '
之前它会有\n
个字符,并且argCount
的值将会变为3
直到public void HighScoreScreen(String HighScores){
//first we need to get rid of what's already there (this works)
remove(title);
remove(newGameButton);
remove(twoPlayerButton);
remove(highScore);
//now adding what I want to show (doesn't work)
highScoreSheet = new JLabel(HighScores);
gbc.gridx = 0;
gbc.gridy = 0;
add(highScoreSheet, gbc);
menu = new JButton("Menu");
gbc.gridx = 0;
gbc.gridx = 1;
add(menu, gbc);
repaint();
}
。
答案 2 :(得分:1)
你想做的是这样的事情:
char** parse_cmdline( const char *cmdline )
{
为1指针分配长度的参数指针数组,并用0开始。
char** arguments = malloc( sizeof(char*) );
arguments[0] = NULL;
在yor命令行中设置char*
指向第一个char
的指针并记住
第一个论点的开头
int argCount = 0, len = 0;
const char *argStart = cmdline;
const char *actPos = argStart;
继续,直到命令行结束。
如果您找到空白,则会有一个新参数,其中包含argStart
和actPos
之间的字符。从命令行分配和复制参数。
while( *actPos != '\n' && *actPos != '\0' )
{
if( cmdline[lineCount] == ' ' && actPos > argStart )
{
argCount++; // increment number of arguments
arguments = realloc( arguments, (argCount+1) * sizeof(char*) ); // allocate argCount + 1 (NULL at end of list of arguments)
arguments[argCount] = NULL; // list of arguments ends with NULL
len = actPos - argStart;
arguments[argCount-1] = malloc( len+1 ); // allocate number of characters + '\0'
memcpy( arguments[argCount-1], actPos, len ); // copy characters of argument
arguments[argCount-1] = 0; // set '\0' at end of argument string
argStart = actPos + 1; // next argument starts after blank
}
actPos++;
}
return arguments;
}
答案 3 :(得分:0)
char ** charArray = malloc(arguments*sizeof(char*));
。这将是char ** charArray的空间。然后,charArray中的每个元素都应该按照您要在该元素中存储的单词的大小进行malloced。然后,您可以将该单词存储在该索引中。
防爆。 *charArray = malloc(sizeof(word));
然后您可以将其存储为**charArray = word;
然而,请注意指针算法。
分段错误肯定是由于您尝试访问未定义空间中的数组中的元素而产生的。这是因为你没有为数组正确地分配空间。