怪异:指针地址不变,但内容偏差 1

weirdness: pointer address doesn't change but contents off by 1

本文关键字:指针 地址 怪异      更新时间:2023-10-16

我交叉发布了这篇文章,因为这可能是一个Pd问题,但也许这里有人知道为什么会发生这样的事情。

简而言之,我有一个dll,我正在一个名为Pd的程序中使用(puredata,用于计算机音乐(。我创建了一个名为recordString的对象,我将其与基本的Pd API结合使用,以创建Pd将读取的dll。Pd只需要访问几个简单的函数。我已经将recordString作为使用Pd API的代码的一部分。

无论如何,recordString对象包含一个char*,我正在使用new创建它(我也尝试过malloc(。当我设置char*的值时,它会正确地设置为HELLOWORLD。我正在输出地址以确保它保持在应该的位置。

我已经确认了这个值是应该的,只是后来当我调用一个函数来获取char*的值时,它不知何故被移动了1个字节。

有人听说过指针将地址更改为值1的情况吗?在没有被告知的情况下?

总之,这是输出,下面是datarecord.cpp 的代码

字符串:HELLOWORLD长度:10地址:32774028地址-2:32578488调用postString字符串:ELLOWORLD长度:9地址:32774028地址-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");
}

您的问题是没有为字符串分配足够的内存

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

+ 1是C风格字符串所具有的nul终止符所必需的。

其他错误包括:

使用delete而不是delete[](new[]应与delete[]配对(。

您的默认构造函数使name未初始化。

赋值运算符会泄漏内存,因为它从不释放旧字符串。CCD_ 7是相同的。

当您输出想要post("address: %d", name)而不是post("address: %d", &this->name)的地址时,您打印的是对象内name的地址,而不是name指向的地址。

我不得不同意Cameron的观点,std::string将把你从所有这些复杂性中拯救出来。

与几个人交谈后,出现了单词对齐和结构填充的话题。该结构最初的代码是

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

由于某种原因,r->name指向的指针的值与4字节的边界对齐。不知道确切的原因,但显然与结构填充有关。做了一些测试来证实这一点,它确实与4字节的边界对齐。

我从结构中删除了recordStringr,并将其放在全局上下文中,它不再受此对齐的影响。

对我来说奇怪的是,它发生在调用之间、不同的范围、不同的时间、运行时。我对编译器或打包/填充结构不太了解,但在运行时发生这样的事情似乎很危险。

无论如何,现在似乎已经通过从结构中删除对象来修复了。

谢谢!我将暂时保留这一点,以防有人在运行时有关于对齐的细节需要添加。