2013-04-06 57 views
0

我交叉發帖,因爲它可能是一個Pd問題,但也許有人在這裏知道爲什麼會發生這樣的事情。古怪:指針地址不會改變,但內容不會改變1

簡而言之,我有一個dll,我在一個名爲Pd(puredata,用於計算機音樂)的程序中使用。我創建了一個名爲recordString的對象,我將它與基本的Pd API一起使用來創建pd將讀取的dll。所有Pd需要訪問的都是一些簡單的功能。我已經使recordString成爲使用Pd API的代碼的一部分。

無論如何,recordString對象包含一個char *,我使用new創建(我也試過malloc)。當我設置char *的值時,它將正確設置爲HELLOWORLD。我輸出地址以確保它保持在應該的位置。

我已經確認該值是應該如此,除了稍後當我調用函數來獲取char *的值時,它已經以某種方式被移動了1個字節。

有沒有人聽說過指針將地址值改爲1的情況?沒有被告知?

總之,這裏的輸出,並遵循對於datarecord.cpp代碼

 
string: HELLOWORLD 
length: 10 
address: 32774028 
address-2: 32578488 

calling postString 
string: ELLOWORLD 
length: 9 
address: 32774028 
address-2: 32578489 

#include "m_pd.h" 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include "datarecord.h" 

using namespace std; 

recordString::recordString() 
    :name(NULL) 
{ 
}; 

recordString::recordString(const char* sourceString) 
{ 
    this->name = new char[strlen(sourceString)+1]; 

    post("-------- in string constructor -----------"); 
    post("address: %d", &this->name); 
    strcpy(this->name, sourceString); 
    post("copy: %s", this->name); 
}; 

recordString::~recordString() 
{ 
    //delete(this->name); 
    delete[] name; 
    name = NULL; 

    //free(this->name); 
}; 

recordString::recordString(const recordString & rhs) 
{ 
    post("-------- in copy constructor -----------"); 
    post("source: %s", rhs.name); 
    post("length: %d", strlen(rhs.name)); 
    post("\n"); 

    this->name = new char[strlen(rhs.name)+1]; 

    strcpy(this->name, rhs.name); 

    post("copy: %s", this->name); 
    post("length: %d", strlen(this->name)); 
    post("address: %d", &name); 
    post("address-2: %d", name); 
    post("\n"); 
} 

recordString & recordString::operator=(const recordString &rhs) 
{ 
    post("-------- in operator= -----------"); 
    post("source: %s", rhs.name); 
    post("length: %d", strlen(rhs.name)); 
    post("\n"); 

    if(name!=NULL) 
    { 
     delete[] name; 
    } 

//this->name = (char*) malloc((strlen(rhs.name))); 
    this->name = new char[strlen(rhs.name)+1]; 

    strcpy(this->name, rhs.name); 

    post("copy: %s", this->name); 
    post("length: %d", strlen(this->name)); 
    post("address: %d", &name); 
    post("address-2: %d", name); 
    post("\n"); 
} 

int recordString::setString(const char * sourceString) 
{ 

    post("-------- in setString -----------"); 
    post("source: %s", sourceString); 
    post("length: %d", strlen(sourceString)); 
    post("\n"); 

    this->name = new char[strlen(sourceString)]; 
    strcpy(this->name, sourceString); 

    post("copy: %s", this->name); 
    post("length: %d", strlen(this->name)); 
    post("address: %d", &name); 
    post("address-2: %d", name); 
    post("\n"); 

    return (this->name == NULL); 
} 


void recordString::postString() 
{ 
    post("string: %s", this->name); 
    post("length: %d", strlen(this->name)); 
    post("address: %d", &name); 
    post("address-2: %d", name); 
    post("\n"); 
} 
+0

注意你的賦值運算符重載應該返回一些東西。 – 2013-04-06 20:57:13

+3

這是C++,而不是C(你有類)。在這種情況下,使用'std :: string'會爲你節省很多的工作,並且可能會加快你的代碼速度。 – Cameron 2013-04-06 20:57:20

+0

要繼續@Cameron的評論,使用標準庫來處理任何事物(通用集合,泛型算法和其他事物的** lot **)將顯着簡化您作爲C++程序員的生活! – 2013-04-06 21:03:06

回答

0

與幾個人交談,話語對齊和結構填充的話題出現了。用於結構最初代碼是

typedef struct _something { 
    t_object x_obj; // *this 
    recordString r; 
} t_something 

,由於某種原因該指針的值由R->名字被對準到一個4字節邊界指向。不知道爲什麼,但顯然與結構填充有關。做了一些測試來證實這一點,並確實將其與4字節邊界對齊。

我從結構中刪除了recordString r,並將其放置在全局上下文中,並且不再受此對齊的影響。

對我而言,奇怪的是它發生在調用之間,在不同的作用域中,在不同的時間,在運行時。我對編譯器或者打包/填充結構不太瞭解,但是在運行時發生這樣的事情似乎很危險。

無論如何,似乎現在通過從結構中刪除對象來修復。

謝謝!如果有人在運行時需要添加關於對齊的細節,我會將其保留一段時間。

3

你的問題是,你不爲你的字符串分配足夠的內存

this->name = new char[strlen(sourceString) + 1]; 

對於C風格字符串具有的nul終止符,需要+ 1

其他錯誤是:

使用deletedelete[]new[]應與delete[]配對)。

您的默認構造函數離開name未初始化。

您的賦值運算符會泄漏內存,因爲它永遠不會釋放舊字符串。 setString是一樣的。

當你輸出你想post("address: %d", name)地址不post("address: %d", &this->name)你打印的是你的name對象內部地址,而不是name指向的地址。

我不得不同意卡梅隆,std::string將免除所有這些複雜性。

+0

謝謝約翰。我做了些改變,我看得更清楚。 當Pd API框架初始化和我(稍後)在該框架中調用函數時發生了一些事情。 「名稱」是私人的,我不增加。 ??? -------- in setString ----------- source:HELLOWORLD length:10 ------- in pd_class_new -------- ---- 多次調用postString ....所有產生這種 副本:HELLOWORLD 長度:10個 地址:32774028個 地址-2:32578488 -------在pd_class_bang ---- -------- 多個呼叫到postString ....全部產生這個 字符串:ELLOWORLD 長度:9 地址:32774028 地址-2:32 578489 – 2013-04-08 13:47:14

+0

我上面發佈了一個修改,因爲它仍然沒有產生預期的行爲。是否有涉及編譯或使用共享庫的內容會影響以此方式處理的內存? – 2013-04-08 14:58:03

+0

@PhilipMiller你的setString函數仍然是錯誤的'this-> name = new char [strlen(sourceString)];'應該是'this-> name = new char [strlen(sourceString)+ 1];'。但是似乎有些奇怪的事情正在發生。我想我需要看到的代碼是與您的dll進行通信時的代碼。你的'name'指針正在增加,你已經有某種內存損壞了。但是,目前我不能說的原因是什麼。 – john 2013-04-08 20:49:39