2013-01-17 77 views
13

以下是3个函数。 main()按预期打印出来。 现在,在mycharstack()字符串存储在堆栈我猜,所以“ch”超出范围,它不应该能够返回字符串。它如何正确工作? 我猜存储在mychar()中的字符串也在堆栈中。它应该正常工作吗? 我想代码和内存泄漏还有其他错误,请告诉我是否有任何错误。使用std :: string我可以更轻松地完成这些清洁工作&。但我想了解char *发生了什么。从函数返回char *

#include <iostream> 
using namespace std; 

char* mychar() 
{ 
    return "Hello"; 
} 

char* mycharstack() 
{ 
    char* ch = "Hello Stack"; 
    return ch; 
} 

char* mycharheap() 
{ 
    char* ch = new char; 
    ch = "Hello Heap"; 
    return ch; 
} 

int main() 
{ 
    cout << "mychar() = " << mychar() << endl; 
    cout << "mycharstack() = " << mycharstack() << endl; 
    cout << "mycharheap() = " << mycharheap() << endl; 

    system("PAUSE"); 
    return 0; 
} 

回答

15

在C++中,字符串处理与例如pascal不同。

char* mycharheap() 
{ 
    char* ch = new char; 
    ch = "Hello Heap"; 
    return ch; 
} 

但这下列:

  1. char* ch = new char;一个字符创建存储器,并将其分配给变量ch
  2. ch = "Hello Heap";分配给变量ch指针只读存储器,其包含字节"Hello Heap\0"。另外,变量ch的原始内容丢失,导致内存泄漏。
  3. return ch;将指针存储到变量ch

你可能想要的是

char* mycharheap() 
{ 
    char* ch = new char[11] /* 11 = len of Hello Heap + 1 char for \0*/; 
    strcpy(ch, "Hello Heap"); 
    return ch; 
} 

strcpy - >您已经有了在ch内存,有空间,11个字符,并且系统会通过字符串从只读部分加油吧的记忆。

在这种情况下会出现泄漏。您将需要写入后删除存储,如:

char* tempFromHeap = mycharheap(); 
cout << "mycharheap() = " << tempFromHeap << endl; 
delete[] tempFromHeap; 

不过,我高度不建议这样做(在被叫分配内存和调用者删除)。对于这种情况,例如,有STL std::string,另一种常见和更合理的方法是在调用者中分配,传递给被调用者,这会将结果“填充”到内存中,并再次在调用者中解除分配。

将导致未定义的行为什么是以下:

char* mycharstack() 
{ 
    char[] ch = "Hello Heap"; /* this is a shortcut for char[11] ch; ch[0] = 'H', ch[1] = 'e', ...... */ 
    return ch; 
} 

这将创建上堆叠阵列与字节"Hello Heap\0",然后尝试指针返回到该阵列的第一个字节(它可以,在调用功能,指向任何东西)

+0

If我刚刚用我在代码中提到的那个替换了mycharheap(),但仍然会泄漏......对吧?在main()中没有人释放分配的内存。 – ontherocks

+0

是的。看到我更新的答案。 – nothrow

+0

因此,对于像mycharheap()这样的函数,不建议将其直接用作其他函数中的参数,这些函数以char *作为输入参数。例如,说有一个函数print(char * char_in);''我不应该像'print(mycharheap());'那样做。这会导致内存泄漏。我对吗? – ontherocks

0

功能mycharheap()泄漏:你让你的指针指向在堆上分配一个char长度的存储区域,然后修改指针指向一个字符串文字存储在只读只有记忆。分配的内存不会被释放。

+0

如何释放分配的内存?我的意思是,在上面的代码中,我在哪里调用delete? – ontherocks

+0

@ontherocks:这个问题是错误的;-)你不应该重新分配指针。如果你想在堆上分配字符串“hello world”,然后分配足够长度的缓冲区('new char [size]'),然后将该字符串复制到该缓冲区中。一旦你将指针返回给调用者,调用者有责任将其删除(通过将结果赋给char *指针并在 –

+0

之后调用该指针上的delete),因此在上面的代码中没有办法释放分配的内存? – ontherocks

1

代码中没有错误只是泄露了char。但这很奇怪。

char* mycharheap() 
{ 
    char* ch = new char; //creates a pointer that points to a new char in the heap 
    ch = "Hello Heap"; //overwrites the pointer with const char - but this cast is legal. 
         //note: pointer to the previous char is lost 
    return ch;   //return the pointer to the constant area where "Hello heap" is stored. 
         //no, "Hello heap" is not on the heap. 
} 

对于“你想什么:”部分,尤索林比我更快。

+0

所以这个也没有任何错误的代码也是类似的,如果不相同的话char * mycharheap() char * ch = new char []; ch =“Hello heap“; return ch; }' – ontherocks

+0

是的,几乎是相同的,他们有同样的问题 - 堆栈上没有'Hello Heap''看看@Yossarian的答案,看看如何实现你想要的东西 – Csq

1

首先,如果您使用的是C++,请使用std::string来表示字符串。

现在你的问题。 char*是指向char(或char的数组)的指针。字符串文字(用引号引起来的东西)是数组类型为char的只读对象,存储在某种只读存储器(堆栈或堆中)中。

由于char*是一个指针,指定它将改变指针。因此,mychar()mycharstack()都返回一个指向存储在只读存储器中的字符串文字的指针。

mycharheap()只是泄漏。您使用new char在堆上分配一个char,然后忘记其地址并返回一个指向字符串文字的指针。我猜你的意思是这样的:

char* mycharheap() { 
    char* ch = new char[strlen("Hello Heap") + 1]; 
    strcpy(ch, "Hello Heap"); 
    return ch; 
} 

然而,再次重申,不C使用char*字符串++。使用std::string

+0

如果我们有下列情况会怎么样:SET_ERROR_MESSAGE(false,(returnErrorCppString()。c_str()));大写字母表示采用可变参数的宏。 – Zingam

+0

@Zingam嗯,什么?这与问题或我的回答有什么关系?你能详细说明吗? – Angew

+0

那么,SET_ERROR_MESSAGE接受const char *的,但根据你的建议我会使用一个函数返回一个std :: string,那么我需要将它转换为const char *才能使用它。 SET_ERROR_MESSAGE由第三方库定义。 – Zingam

2

mycharstack()字符串存储在堆栈中我猜,所以“ch”超出范围,它不应该能够返回字符串。它如何正确工作?

字符串文字是指存在于静态内存中的数组。我希望你知道三个内存区域:自动内存(又名堆栈),自由存储(又名堆)和静态内存。堆栈中的东西只是一个指针变量,你可以通过值返回指针的值(它存储的地址)。所以一切都很好,除非事实上你应该使用const char*作为指针类型,因为你不允许修改字符串文字引用的数组。

我猜存储在mychar()中的字符串也在栈上。

字符串(字符数组)存储在静态内存中。 char*只是一个可以用来传递地址的指针类型。 const也缺失。

我猜还有其他代码和内存泄漏错误,请让我知道如果有的话。

泄漏在您的第三个功能。您只为堆中的一个字符分配内存,并将其地址存储到名为ch的变量中。通过以下分配,您可以用字符串文字的地址覆盖此地址。所以,你在泄漏记忆。

你似乎想到char*作为字符串变量的类型。但事实并非如此。这是指向字符或字符序列的指针的类型。指针和它可能指向的字符串是两个独立的东西。你可能应该使用的是std :: string。

0

以下示例是我试图从函数调用中获取信息时出现的问题。

#include <iostream> 
#include <cstring> 
using namespace std; 

char* Xout(char* message); 

int main() 
{ 
const int LEN = 64; 
char message[LEN], *x; 

cin>>message; 

x=Xout(message); 
cout<<x; 
return 0; 
} 

char* Xout(char* message) 
{ 
int length=strlen(message); 
for(int i = 0; i < length; i++) 
{ 
    message[i] = 'X'; 
} 
return message; 
}