分配和传递字符串的正确方法是什么?

时间:2014-11-24 20:42:22

标签: c windows

我有一个字符串,我为此分配内存。之后,我将此字符串传递给另一个函数,然后从第二个函数将其传递给第三个函数。问题是,在tird函数完成后,我可以访问/使用变量。但是在第二个函数完成后,我无法在第一个函数中访问它的值。显然,我做错了什么,但我不知道。 有人可以帮帮我吗? 当然,如果有人有更好的想法,我应该怎么做我想要的,我也会很感激。 到目前为止我的代码:

#define MAX_SIZE 100

void Func1()
{
   char *Test = NULL;
   Test = ( char * )malloc( MAX_SIZE*sizeof( char ) );
   if ( Test == NULL )
   {
      return;
   }

   Func2( Test );

   if ( Test!= NULL ) free( Test);
}

void Func2(char *string)
{
    Func3( &string);
}

void Func3( char **string)
{
    if (Len > MAX_SZIE )
    {
         char *tmp = NULL;
         tmp = ( char * )realloc( *string, Len + 1 );
         if ( !tmp )
         {
               return;
         }
         *string = tmp;
         memset( *string, 0, sizeof( *string ) );
    }
    memcpy( *string, SomeOtherString, Len );
    free( SomeOtherString );
}

提前致谢!

更新 使用我现在拥有的当前代码更新了该功能:

bool __stdcall Function( DataToSendBack *DataArray )
{
char *Result = NULL;
char InString[ MAX_SIZE ] = { 0 };
int DataLen = 0;
bool bRetVal = false;

__try
{
    Result = ( char * )malloc( MAX_SIZE );
    if ( Result == NULL )
    {
        __leave;
    }

    memset( InString, 0, sizeof( InString ) );
    memset( Result, 0, sizeof( Result ) );

    memcpy( InString, DataArray->StringIn, strlen( DataArray->StringIn ) );

    Result = GetInfo( InString, Result, &DataLen );
    if ( Result == NULL )
             {
        MessageBoxA(NULL,"error",NULL,NULL);
                    __leave;
             }

    if ( strlen( ErrorMsg ) > 0 ) strcpy( DataArray->ErrorMessage, ErrorMsg );

    if ( DataArray->RequiredSize < DataLen )
    {
        DataArray->RequiredSize = DataLen;
        strcpy( DataArray->ErrorMessage, ErrorMsg );
        __leave;
    }

    DataArray->Result = _strdup( Result );
    bRetVal = true;
}
__finally
{
    if ( Result != NULL ) free( Result );
}

return bRetVal;

}

char * GetInfo( char *String, char *Result, int *DataLen )
{
  bool bRetVal = false;

__try
{
    if ( DoStuff( String, &Result, DataLen ) )
    {
        bRetVal = true;
    }
}
__finally
{
    // free other things
}

return Result;
}

 bool DoStuff( char *MyString, char **Result, int *DataLen )
 {
__try
{
    //Call function which returns dwsize
    *DataLen = dwSize * 2;
            OtherString = SomFunction();
    if ( strlen( OtherString ) > MAX_SIZE )
    {
        char *tmp = NULL;
        tmp = ( char * )realloc( *Result, strlen( OtherString ) );
        if ( !tmp )
        {
            __leave;
        }
        *Result = tmp;
        memset( *Result, 0, sizeof( *Result ) );
    }

    memcpy( *Result, OtherString, strlen( OtherString ) );

    free( OtherString );

    bretVal = true;
}
__finally
{
    // free other things
}

return bretVal;
}

2 个答案:

答案 0 :(得分:2)

Func3()修改Func1()分配的指针。您需要将其传递回Func1():

void Func1()
{
   char *Test = NULL;
   if (NULL == (Test = malloc(MAX_SIZE) ) {
      // Handle case of OOM error
      return;
   }

   // Func2 may modify Test
   Test = Func2( Test );

   if (NULL == Test) {
       // Handle case of error in Func3
   }
   free(Test); // Test = NULL;
}

/**
 * Reads and modifies (through a call to Func3) a pointer to string
 */
char * Func2(char *string)
{
    Func3( &string);
    return string;
}

此外,在Func3()中,您需要:

memset( *string, 0, Len + 1 );

将整个字符串归零。

但实际上你正在将OtherString写入*string,因此将所有这些字节归零,就像WhozCraig指出的那样,是不必要的。你应该做的是确保你有足够的空间,并在字符串之后立即将一个字节归零,如果则需要。那就是

strncpy(*string, OtherString, Len);
(*string)[Len] = 0x0;

或更有效率(因为strncpy将归零OtherString副本之后的任何内容,最多为Len字节)

size_t new_len = strlen(OtherString);
if (new_len <= Len) {
    // Copy, including last zero
    memcpy(*string, OtherString, new_len+1);
} else {
    // Copy Len bytes, from 0 to Len-1
    memcpy(*string, OtherString, Len);
    // Zero last byte to make it a valid C string
    (*string)[Len] = 0x0;
}

或     size_t new_len = min(Len,strlen(OtherString));     memcpy(* string,OtherString,new_len);     //将最后一个字节归零以使其成为有效的C字符串     (* string)[new_len] = 0x0;

更新

出于测试目的,这是我使用的Func3():

#define OtherString     "To be or not to be, that is the question\n"
#define Len             10240
#define min(a,b)        (((a)<(b))?(a):(b))

void Func3( char **string)
{
     char *tmp = realloc( *string, Len+1);
     if (NULL == tmp)
     {
           return;
     }
     *string = tmp;
     size_t new_len = strlen(OtherString);
     new_len        = min(Len, new_len);
     memcpy(*string, OtherString, new_len);
     // Zero last byte to make it a valid C string
     (*string)[new_len] = 0x0;
}

在一种情况下,它返回&#34;要成为或不成为&#34;,在另一个中(Len = 16)它返回&#34;成为或不成为&#34;,如预期的那样。< / p>

答案 1 :(得分:0)

realloc()点击Func3()中的字符串Func1()。但是,新的,可能修改的指针永远不会返回到Func2(),因为Func2()按指针获取指针,而不是指针。因此,您将访问可能已释放的内存区域。

解决方案:根据您的需要,您可能希望通过指针将原始字符串传递给Func1()(也可能传递给{{1}})。