分段错误
Segmentation Error
我正在尝试在 Linux 中实现我自己的 shell。我从用户那里获取输入并解析它。但是当我在数组中复制我的标记时它会出现分段错误。我无法解决这个问题。
这是我实现的代码
#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
using namespace std;
int main ()
{
char * input;
string insert;
cout<<"My Shell $";
getline(cin,insert);
input= new char [insert.size()+1];
strcpy(input, insert.c_str());
char * token;
char * parsed[100];
int count;
token=strtok(input, " ");
while (token!=NULL)
{
strcpy(parsed[count],&(token[count]));
count++;
token=strtok(NULL, " ");
}
}
变量int count未定义,意思是可以是随机值,改成int count = 0;
你没有初始化变量count
,它的值是未定义的(可能很大,所以程序从内存中读取会失败)。你应该使用 int count = 0;
。
并且数组 parsed
中的元素未初始化且未指向分配的内存。您调用 strcpy
的行为也是未定义的。在调用 strcpy
之前添加 parsed[count] = new char[strlen(token) + 1];
。完成所有操作后不要忘记使用 delete
。
最后,我认为你没有正确使用strtok
。你为什么使用 &(token[count])
?也许您应该将其替换为 token
.
只需将您的计数变量初始化为 0
请尝试下面的代码#
#include <iostream>
#include <unistd.h>
#include <string.h>
using namespace std;
int main (void)
{
char* input = NULL;
string insert;
cout<<"My Shell $";
getline(cin, insert);
input= new char[insert.size() + 1];
strcpy(input, insert.c_str());
char* token = NULL;
char* parsed[100];
for (int index = 0; index < 100; index++)
{
parsed[index] = NULL;
}
int count = 0;
token = strtok(input, " ");
while ( token != NULL)
{
strcpy(parsed[count], &(token[count]));
count++;
token = strtok(NULL, " ");
}
return 0;
}
#include <string.h>
没有
如果您需要 C 函数,请使用 <cstring>
,这会将它们放在 std::
命名空间中。
但是您不想要 C 函数,您想要C++ <string>
。相信我,你相信。
using namespace std;
为了示例的缘故,我将让它通过。在任何生产代码中摆脱这种特殊习惯。
getline(cin,insert);
很好。您已准备好使用 C++。
input= new char [insert.size()+1];
strcpy(input, insert.c_str());
不好。你只是把你的手绑在你的背上。
char * parsed[100];
一个包含 100 个指向 char 的指针的数组。只是指针,未初始化,指向任何地方。
int count;
未初始化。
token=strtok(input, " ");
C。 不寒而栗.....
strcpy(parsed[count],&(token[count]));
未定义的行为。 count
没有初始化,即使 确实 恰好在 0 到 99 之间,parsed[count]
仍然没有指向有效的内存,所以向它复制一些东西会做坏事
此外,您的令牌在 token
,而不是 token[count]
...
count++;
未初始化加1就是UB,还是未初始化。 ;-)
}
你忘了delete [] input
。
让我建议一种不同的、更像 C++ 的方法,它仍然会为您提供指向每个标记的指针数组(如果您坚持这样做):
getline( cin, input );
// turn spaces to null bytes
std::replace( input.begin(), input.end(), ' ', '[=20=]' );
// need an additional one for the finds below to work
input.append( '[=20=]' );
// vector takes away all of that manual memory management
std::vector< char * > parsed;
size_t i = 0;
// skip leading (ex-) spaces
while ( ( i = input.find_first_not_of( '[=20=]', i ) ) != std::string::npos )
{
// push the pointer to the token on the vector
parsed.push_back( input.data() + i );
// skip to end of token
i = input.find( '[=20=]', i );
}
此时,parsed
是 char *
的 vector
到 input
中的标记(至少,只要 input
本身是仍在范围内)。您可以使用 parsed.size()
检查它的大小,并使用 parsed.data()
作为 "naked" 数组访问它,尽管我相信您会发现 vector
更方便。
如果您不想保留 input
,请替换为
std::vector< char * > parsed;
和
std::vector< std::string > parsed;
和
parsed.push_back( input.data() + i );
和
parsed.push_back( std::string( input.data() + i ) );
并且您在 vector
.
中有一个 副本 的令牌
请注意,这仍然是相当粗暴的处理,因为即使引号内的空格也会被检测为 "end of token",但至少它是 C++,C 字符串处理的 none。
Please try to use this code. I tried in VS2010 and it is working fine now.
#include <iostream>
#include <string.h>
#include <string>
using namespace std;
int main (void)
{
char* input = NULL;
string insert;
cout<<"My Shell $";
/* getline(cin, insert);*/
std::getline(cin, insert);
input= new char[insert.size() + 1];
strcpy(input, insert.c_str());
char* token = NULL;
char* parsed[100] = {0};
int count = 0;
token = strtok(input, " ");
while ( token != NULL)
{
parsed[count] = token;
count++;
token = strtok(NULL, " ");
}
for ( int index = 0; index<count; index++ )
{
cout << parsed[index] << std::endl;
}
system("pause");
return 0;
}
我正在尝试在 Linux 中实现我自己的 shell。我从用户那里获取输入并解析它。但是当我在数组中复制我的标记时它会出现分段错误。我无法解决这个问题。
这是我实现的代码
#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
using namespace std;
int main ()
{
char * input;
string insert;
cout<<"My Shell $";
getline(cin,insert);
input= new char [insert.size()+1];
strcpy(input, insert.c_str());
char * token;
char * parsed[100];
int count;
token=strtok(input, " ");
while (token!=NULL)
{
strcpy(parsed[count],&(token[count]));
count++;
token=strtok(NULL, " ");
}
}
变量int count未定义,意思是可以是随机值,改成int count = 0;
你没有初始化变量count
,它的值是未定义的(可能很大,所以程序从内存中读取会失败)。你应该使用 int count = 0;
。
并且数组 parsed
中的元素未初始化且未指向分配的内存。您调用 strcpy
的行为也是未定义的。在调用 strcpy
之前添加 parsed[count] = new char[strlen(token) + 1];
。完成所有操作后不要忘记使用 delete
。
最后,我认为你没有正确使用strtok
。你为什么使用 &(token[count])
?也许您应该将其替换为 token
.
只需将您的计数变量初始化为 0
请尝试下面的代码#
#include <iostream>
#include <unistd.h>
#include <string.h>
using namespace std;
int main (void)
{
char* input = NULL;
string insert;
cout<<"My Shell $";
getline(cin, insert);
input= new char[insert.size() + 1];
strcpy(input, insert.c_str());
char* token = NULL;
char* parsed[100];
for (int index = 0; index < 100; index++)
{
parsed[index] = NULL;
}
int count = 0;
token = strtok(input, " ");
while ( token != NULL)
{
strcpy(parsed[count], &(token[count]));
count++;
token = strtok(NULL, " ");
}
return 0;
}
#include <string.h>
没有
如果您需要 C 函数,请使用 <cstring>
,这会将它们放在 std::
命名空间中。
但是您不想要 C 函数,您想要C++ <string>
。相信我,你相信。
using namespace std;
为了示例的缘故,我将让它通过。在任何生产代码中摆脱这种特殊习惯。
getline(cin,insert);
很好。您已准备好使用 C++。
input= new char [insert.size()+1];
strcpy(input, insert.c_str());
不好。你只是把你的手绑在你的背上。
char * parsed[100];
一个包含 100 个指向 char 的指针的数组。只是指针,未初始化,指向任何地方。
int count;
未初始化。
token=strtok(input, " ");
C。 不寒而栗.....
strcpy(parsed[count],&(token[count]));
未定义的行为。 count
没有初始化,即使 确实 恰好在 0 到 99 之间,parsed[count]
仍然没有指向有效的内存,所以向它复制一些东西会做坏事
此外,您的令牌在 token
,而不是 token[count]
...
count++;
未初始化加1就是UB,还是未初始化。 ;-)
}
你忘了delete [] input
。
让我建议一种不同的、更像 C++ 的方法,它仍然会为您提供指向每个标记的指针数组(如果您坚持这样做):
getline( cin, input );
// turn spaces to null bytes
std::replace( input.begin(), input.end(), ' ', '[=20=]' );
// need an additional one for the finds below to work
input.append( '[=20=]' );
// vector takes away all of that manual memory management
std::vector< char * > parsed;
size_t i = 0;
// skip leading (ex-) spaces
while ( ( i = input.find_first_not_of( '[=20=]', i ) ) != std::string::npos )
{
// push the pointer to the token on the vector
parsed.push_back( input.data() + i );
// skip to end of token
i = input.find( '[=20=]', i );
}
此时,parsed
是 char *
的 vector
到 input
中的标记(至少,只要 input
本身是仍在范围内)。您可以使用 parsed.size()
检查它的大小,并使用 parsed.data()
作为 "naked" 数组访问它,尽管我相信您会发现 vector
更方便。
如果您不想保留 input
,请替换为
std::vector< char * > parsed;
和
std::vector< std::string > parsed;
和
parsed.push_back( input.data() + i );
和
parsed.push_back( std::string( input.data() + i ) );
并且您在 vector
.
请注意,这仍然是相当粗暴的处理,因为即使引号内的空格也会被检测为 "end of token",但至少它是 C++,C 字符串处理的 none。
Please try to use this code. I tried in VS2010 and it is working fine now.
#include <iostream>
#include <string.h>
#include <string>
using namespace std;
int main (void)
{
char* input = NULL;
string insert;
cout<<"My Shell $";
/* getline(cin, insert);*/
std::getline(cin, insert);
input= new char[insert.size() + 1];
strcpy(input, insert.c_str());
char* token = NULL;
char* parsed[100] = {0};
int count = 0;
token = strtok(input, " ");
while ( token != NULL)
{
parsed[count] = token;
count++;
token = strtok(NULL, " ");
}
for ( int index = 0; index<count; index++ )
{
cout << parsed[index] << std::endl;
}
system("pause");
return 0;
}