【问题标题】:Using to strcpy() to get parts of a char* causes a program crash使用 strcpy() 获取 char* 的一部分会导致程序崩溃
【发布时间】:2011-06-13 04:24:47
【问题描述】:

我正在尝试从 char* 中获取位,然后将其存储在地图中。我使用 strcpy 和 strncpy 来执行此操作,但是当我使用 strncpy 时我的程序崩溃(它可以编译但在运行时崩溃)。

为什么我的程序会崩溃?如何成功地从 char* 中获取位并将它们存储在地图中?

编辑:在听取建议后,我已经初始化了 char*,但它仍然崩溃?

// I did the following
char* variable = "";  
char* value    = ""; 


map <string, string> GetEvironmentVariablesEx()
{
   map <string, string> envVariables;
   char* environVar = GetEnvironmentStrings();
   char* pos        = strchr( environVar, '\0' );

   // This is what environVar contains: environVar = "=::=::\0APPDATA=c:/users/user1/desktop\0OS=windowsNT\0\0"; // note the string is double null terminated

   // Skip over the "=::=::\0" of the environVar string
   if ( pos != NULL ) { environVar = ++pos; pos = strchr( environVar, '\0' ); }
   else return envVariables;


   while ( true )
   {
       char* delim = strchr( environVar, '=' );
       char* variable;
       char* value;

       if ( delim == NULL ) { printf("Environment variable string is badly formatted"); break; }

       // The crash occurs at the below line: the crash occurs at runtime
       strncpy( variable, environVar, strlen(delim) );  
       strcpy( value, environVar+strlen(delim) );  
       printf( "Variable is: %s = %s \n", variable, value );

       envVariables.insert( pair<string, string>(string(variable), string(value)) );
       environVar = ++pos;

       // find the "\0\0" that identifies the end of environVar
       if ( pos != NULL && *pos == 0 ) { break; }

       pos = strchr( environVar, '\0' );
   }

   FreeEnvironmentStrings( environVar ); 
   return envVariables;       
}

【问题讨论】:

  • 为什么你这么坚持使用更难使用的&lt;cstring&gt;函数而不是C++的std::string函数?
  • 你认为strchr(environVar, '\0')会在什么情况下返回NULL?

标签: c++ winapi cstring


【解决方案1】:

崩溃的原因如下:

char* variable; // un allocated or uninitialized
char* value; // un allocated or uninitialized

最好的方法是使用std::string。例如

std::string variable, value;
variable = environVar;
value = environVar + strlen(delim); 

在旁注中,您应该在遇到时从函数中return(或作为错误处理):

if ( delim == NULL )

【讨论】:

    【解决方案2】:

    我看到您正在将字符串复制 (strncpy) 到 variable

    variable 被声明为char*,但我没有看到您为它分配任何内存,或者以其他方式为variable 分配值。

    因此,variable 包含一个随机内存地址,而您正在将您的一部分 environVar 复制到一块未知的内存中,从而导致崩溃。

    要解决此问题,您应该在调用strncpy 之前使用mallocvariable 分配一些内存。

    编辑:在您最近的更改之后,您的代码现在有:

    char* variable = ""; 
    

    及以后:

    char* variable;
    

    variable 的第二个声明仍然未初始化,并隐藏(阴影)第一个声明。因此,您根本没有解决问题。

    当我建议使用malloc 分配内存时,这就是我所说的:

    variable = malloc(strlen(delim)); 
    strncpy( variable, environVar, strlen(delim) );  
    

    请注意,无论何时分配内存,例如使用malloc,都必须准备好在完成后释放它。否则你的程序会有内存泄漏。

    【讨论】:

    • 为什么建议使用malloc 而不是std::vector&lt;char&gt;
    【解决方案3】:
    char* variable;  
    char* value; 
    

    在将任何数据复制到这些之前,您需要为其动态分配内存或使其成为堆栈上的数组。这些只是指针,它们没有任何内存可以将任何数据放入其中。

    要将 char* 转换为字符串以添加到地图中,请使用:

    char* data = ...; 
    int size = ...; 
    std::string myString(data, size); 
    

    编辑:理想情况下,您应该使用vector 来管理您的字符串,而无需担心动态分配或事先不知道字符串的最大大小。

    vector<char>value;    
    vector<char>variable;
    

    这样您就不必再担心大小了,矢量本身会自动增长到大小。

    【讨论】:

    • 为什么建议手动管理动态分配的数组而不是使用std::vector&lt;char&gt;
    • @James McNellis:这是一个最有效、最合适的解决方案,OP 似乎真的涉足过程 C++ 领域(坚持使用cstring
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多