0

这是我的问题。

我有一个定期修改 char* 的类。

还有另一个类,需要能够读取这个值。所以我想将 char* 传递给第二个类的构造函数,以便它可以在需要时检查值。

让我举一个我对另一个参数的实现示例,它是布尔类型:

在 A 类:

bool f_valid = false; // global

m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall(&f_valid))); 

B类:

struct handleCall 
{
    bool* m_dataValid;

    handleCall(bool* result) 
    {
        // saving the pointer to the boolean that I want to change
        m_dataValid = result; 
    }

    method()
    {
        if (smth) 
        { 
            (*m_dataValid) = false;
        }
    }
};

到目前为止一切顺利 - 这似乎有效。两个类都可以更改和访问此布尔值。

现在我需要用 char* 做同样的事情(我不能使用字符串,所以我想这是存储短文本的最佳方式,比如 url 地址?)。

所以这是我写的:

A类:

const char* f_url = "blah blah"; // global

m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall2(&f_url)));

C类:

struct handleCall2 
{
    char ** m_url;

    handleCall2(char** url)
    {
        // saving the pointer to the char*
        m_url= url;
        std::cout << (*m_url) << std::endl; // prints out url fine
    }

    method() 
   {
        std::cout << (*m_url) << std::endl; // by this time the value has been changed by ClassA, and I print out some rubbish - symbols, squares, etc.
    }
};

我想问题是因为字符串已经改变了,它的地址也改变了?我真的很困惑 - 有人可以告诉我发生了什么,在这种情况下我该怎么办?

更新:

看起来问题出在我如何修改char *:

f_url = "new text"; // works fine

f_url = fileUrl.c_str(); // doesn't work! I get rubbish in the value when I try to access it from ClassB

strcpy(m_url, fileUrl.c_str()); // I also removed const from the variable and tried this - got a crash "access violation using location" :(

有没有其他方法可以将字符串的值写入 char *?

4

5 回答 5

0

该字符串实际上并未存储在f_url. 该字符串存储在其他地方,并且f_url是指向其他地方的指针。

如果你这样做:

    f_url = "new text"; // works fine

当你的程序被编译时,它会"new text"在其中的某个地方包含字符串。f_url将指向这一点 - 指向程序本身中间的一些内存。


    f_url = fileUrl.c_str(); // doesn't work! I get rubbish in the value when I try to access it from ClassB

fileUrl是一个 std::string。fileUrl有自己的指向字符串的指针,c_str 返回。由于fileUrl负责管理此字符串,因此当fileUrl超出范围时,内存可能会被重新用于其他用途 - 它不知道您仍在使用该内存。


    // I assume you meant f_url here, not m_url
    strcpy(f_url, fileUrl.c_str()); // I also removed const from the variable and tried this - got a crash "access violation using location" :(

这取决于f_url实际指向的内容。如果f_url指向程序中间的一些内存(如f_url = "blah blah";),那么这将崩溃。通常,这表明存在错误,因此操作系统不允许您这样做。

如果允许,可能会发生这种情况:

char *s = "hello world";
strcpy(s, "abracadabra");

printf("hello world"); // prints "abracadabra"


您需要做的是获取自己的内存块来保存字符串,并在完成后释放它:

f_url = new char[fileUrl.length() + 1];
strcpy(f_url, fileUrl.c_str());

// when you don't need the string any more
delete [] f_url;

或者:

f_url = strdup(fileUrl.c_str());

// when you don't need the string any more
free(f_url);

或者只是f_urlstd::string您处理内存管理。(这是最简单的解决方案!)

于 2013-11-19T08:12:32.360 回答
0
const char* f_url = "blah blah"; // global

Maybe you misunderstand this line? The const qualifier is when you are placing it, referring to the keyword left of it. It's allowed to take it as first keyword but then, AND ONLY then, it is referring to its right ;) So your declaration says: (const char) *f_url so its an pointer to an const char. And I'm guessing (I don't know what's the way you are modifying it's value in that class) you get it by your self, why modifying a const char value could end in rubbish output, don't you? I suggest you want to declare it as

char *const f_url = "blah blah";

this is

char (* const) f_url

so f_url is an constant address-value which is pointing into an modifiable area. But even this wouldn't make that much sense, because "blah blah" is a address of a const memory area, so you cant modify ("blah blah")[count] = Anything; anyway.

So you should just do

char *const f_url = ThisIsACharArray[count];

and access the char array aka String about f_url.

Or the better way for you, as I would guess, just keep the const out of the declaration and allocate modifiable memory by your self ;)

于 2013-08-10T01:39:53.977 回答
0
const char* f_url = "blah blah";

这个声明意味着你有一个指向常量字符串的指针。所以你不能做

strcpy(f_url, "hello world"); // copy to the preallocated place

但是你可以

f_url = "hello world"; // do pointer assignment

如果您有下一种情况:

class ClassA {
const char* f_url = "blah blah";
public: 
    void method() {
        f_url = "hello world";
    }
};

class ClassB {
    char** m_url;
public:
    void print() {
        cout << (* m_url); // m_url points to a string, allocated on the stack of ClassA::method()
    }
};

请记住,字符串"hello world"是在ClassA::method(). ClassA::method()退出时该指针不再有效。解决我接下来提出的问题:

class ClassA {
static const int max_path = 256; 
char f_url[max_path];
public: 
    void method() {
        strcpy(f_url, "hello world");
    }
};

class ClassB {
    char** m_url;
public:
    void print() {
        cout << (* m_url);
    }
};
于 2013-08-09T12:00:12.060 回答
0

我认为访问char *.

我写了一个示例代码,它对我有用。可能是你的另一个问题:

顺便说一句,这是我的代码供您参考:

#include <iostream>

class ClassThatPrints
{
private:
    const char **m_url;

public:
    ClassThatPrints(const char ** url)
    {
        m_url = url;
        std::cout << (*m_url) << std::endl;
    }

    void PrintAfterModify(void)
    {
        std::cout << (*m_url) << std::endl;
    }
};

class ClassThatModifies
{
private:
    const char *m_charPointer;
    ClassThatPrints *m_ClassThatPrints;
public:
    ClassThatModifies()
    {
        m_charPointer = "this is the original string";
        std::cout << "Printing before modification:" << std::endl;
        m_ClassThatPrints = new ClassThatPrints(&m_charPointer);
    }

    ~ClassThatModifies() {
        delete m_ClassThatPrints;
    }

    void ModifyStringAndPrint(void)
    {
        m_charPointer = "this is a modified string";
        std::cout << "Printing after modification:" << std::endl;
        m_ClassThatPrints->PrintAfterModify();
    }
};

int main()
{
    ClassThatModifies objClassThatModifies;
    objClassThatModifies.ModifyStringAndPrint();

}
于 2013-08-09T12:12:54.667 回答
0

如果你有这样的事情:

void addHandler() {
    const char* f_url = "blah blah";
    m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall2(&f_url)));
}

void doStuff() {
    addHandler();
    m_eventCatcher.callProxy();
}

那么问题是当 addHandler 返回时 f_url 超出范围。如果是这种情况,那么您的布尔版本也有问题,并且(*m_dataValid) = false;覆盖了其他一些数据。

于 2013-08-09T12:31:01.947 回答