在 C++ 中将结构指针设置为 null 时,存储的值消失

发布于 2024-11-04 09:14:32 字数 1917 浏览 0 评论 0原文

我正在编写一个 C++ 应用程序来在大型歌词数据库中进行单词搜索。首先,我将每个单词放入一个 Word 结构中,如下所示:

struct Word{
    char* clean;
    int size;
    int position;
    SongId id;
    Word* same;
    Word* diff;
};

我有一个“makeNode”函数,它执行以下操作:

  1. 接受每个单词
  2. 创建一个新的 Word 结构并将该单词添加到其中
  3. 创建一个Word* 称为指向新单词的节点,
  4. 将指针存储在哈希表中。

在我的 makeNode 函数中,我将 node->clean 设置为我的“clean”词。我可以通过计算节点->干净来打印这个词。但是当我将node->same设置为NULL时,我丢失了node->clean。我不会丢失节点->位置或节点->大小。如果我删除将 node->same 分配给 NULL 的行,我不会丢失 node->clean。

char* clean = cleanse(word);
Word* node = new Word;
node->size = strlen(word);
node->clean = clean;
cout<<"MADE NODE FOR "<<node->clean<<endl;
node->position = position;
cout<<"4 node clean: "<<node->clean<<endl;
node->id = id;
cout<<"5 node clean: "<<node->clean<<endl;
node->same = NULL;
cout<<"6 node clean: "<<node->clean<<endl;
cout<<"node position: "<<node->position<<endl;
cout<<"node size: "<<node->size<<endl;
node->diff = NULL;

产生以下输出:

MADE NODE FOR again
4 node clean: again
5 node clean: again
6 node clean:
node position: 1739
node size: 6
0 node clean:
1 node clean:
3 node clean: 

任何人都可以帮助我克服这个错误吗?如果您需要更多信息,请告诉我。提前致谢!

编辑:这是清理功能。

char* SongSearch::cleanse(char* dirty)
{

string clean;
int iter = 0;
while (!isalnum(dirty[iter]))
{
    iter++;
}
while(dirty[iter]!='\0')
{
    clean += dirty[iter];
    iter++;
}

int backiter = clean.length() - 1;
while(!isalnum(clean[backiter]))
{
    clean.erase(backiter, 1);
    backiter--;
}


char c;
  for (int i = 0; i<clean.length(); i++)
{
    c = tolower(clean[i]);
    clean[i] = c;
}

char* toReturn = (char*)(clean.c_str());
return toReturn;
}

I'm writing a C++ application to do a word search across a large database of song lyrics. to start, I'm taking each word and putting it into a Word struct that looks like this:

struct Word{
    char* clean;
    int size;
    int position;
    SongId id;
    Word* same;
    Word* diff;
};

I have a "makeNode" function that does the following:

  1. takes in each word
  2. creates a new Word struct and adds the word to it
  3. creates a Word* called node which points to the new word
  4. stores the pointer in a hash table.

In my makeNode function, I set node->clean to my "clean" word. I can print the word by cout'ing node->clean. But when I set node->same to NULL, I lose node->clean. I don't lose node->position or node->size. If I remove the line where I assign node->same to to NULL, I do not lose node->clean.

char* clean = cleanse(word);
Word* node = new Word;
node->size = strlen(word);
node->clean = clean;
cout<<"MADE NODE FOR "<<node->clean<<endl;
node->position = position;
cout<<"4 node clean: "<<node->clean<<endl;
node->id = id;
cout<<"5 node clean: "<<node->clean<<endl;
node->same = NULL;
cout<<"6 node clean: "<<node->clean<<endl;
cout<<"node position: "<<node->position<<endl;
cout<<"node size: "<<node->size<<endl;
node->diff = NULL;

yields the following output:

MADE NODE FOR again
4 node clean: again
5 node clean: again
6 node clean:
node position: 1739
node size: 6
0 node clean:
1 node clean:
3 node clean: 

Can anyone help me get past this error? If you need more info, let me know. Thanks in advance!

EDIT: here is the cleanse function.

char* SongSearch::cleanse(char* dirty)
{

string clean;
int iter = 0;
while (!isalnum(dirty[iter]))
{
    iter++;
}
while(dirty[iter]!='\0')
{
    clean += dirty[iter];
    iter++;
}

int backiter = clean.length() - 1;
while(!isalnum(clean[backiter]))
{
    clean.erase(backiter, 1);
    backiter--;
}


char c;
  for (int i = 0; i<clean.length(); i++)
{
    c = tolower(clean[i]);
    clean[i] = c;
}

char* toReturn = (char*)(clean.c_str());
return toReturn;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

枫以 2024-11-11 09:14:32

问题可能是在 cleanse 中,您返回 clean.c_str()

当 clean 不再存在(即函数退出时)时,该指针值将不再有效。它不再保证指向任何东西,因此您能够按预期“再次”看到该字符串纯属运气。

我怀疑发生的情况是 cleanse 中的字符串 clean 的数据占用的内存已被重新用于结构word,但不会立即被覆盖。碰巧的是,用于保存第一个 a 的字节现在保存了结构体的 same 成员的一部分。因此,当您向 node->same 写入空指针时,它的效果是向 node->clean 指向的位置写入 0 字节。此后,它似乎指向一个空字符串。

The problem is probably that in cleanse, you return clean.c_str().

That pointer value ceases to be valid when clean ceases to exist, which is when the function exits. It is no longer guaranteed to point to anything, so it's pure luck that you're ever seeing the string "again" as expected.

What I suspect happens is that the memory that used to be occupied by the data for the string clean in cleanse, has been re-used for the structure word, but is not immediately overwritten. It just so happens that the byte that used to hold the first a now holds part of the same member of your struct. So, when you write a null pointer to node->same, it has the effect of writing a 0 byte to the location pointed to by node->clean. Thereafter, it appears to point to an empty string.

眼泪淡了忧伤 2024-11-11 09:14:32

您需要将代码减少到显示问题的最小示例,然后发布该示例。

以下代码无法显示问题。 main 的内容和 Word 的定义是从您的代码中复制的,然后我根据需要添加了代码以使其编译:

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

typedef int SongId;

struct Word{
    char* clean;
    int size;
    int position;
    SongId id;
    Word* same;
    Word* diff;
};

char *cleanse(const char *w) {
    return (char *)w;
}
const char *word = "again ";
const int position = 1739;
const int id = 0;

int main() {
    char* clean = cleanse(word);
    Word* node = new Word;
    node->size = strlen(word);
    node->clean = clean;
    cout<<"MADE NODE FOR "<<node->clean<<endl;
    node->position = position;
    cout<<"4 node clean: "<<node->clean<<endl;
    node->id = id;
    cout<<"5 node clean: "<<node->clean<<endl;
    node->same = NULL;
    cout<<"6 node clean: "<<node->clean<<endl;
    cout<<"node position: "<<node->position<<endl;
    cout<<"node size: "<<node->size<<endl;
    node->diff = NULL;
}

输出为:

MADE NODE FOR again 
4 node clean: again 
5 node clean: again 
6 node clean: again 
node position: 1739
node size: 6

You need to reduce your code to a minimal example which displays the problem, and post that.

The following code fails to display the problem. The contents of main and the definition of Word are copied from your code, then I have added code as necessary to get it to compile:

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

typedef int SongId;

struct Word{
    char* clean;
    int size;
    int position;
    SongId id;
    Word* same;
    Word* diff;
};

char *cleanse(const char *w) {
    return (char *)w;
}
const char *word = "again ";
const int position = 1739;
const int id = 0;

int main() {
    char* clean = cleanse(word);
    Word* node = new Word;
    node->size = strlen(word);
    node->clean = clean;
    cout<<"MADE NODE FOR "<<node->clean<<endl;
    node->position = position;
    cout<<"4 node clean: "<<node->clean<<endl;
    node->id = id;
    cout<<"5 node clean: "<<node->clean<<endl;
    node->same = NULL;
    cout<<"6 node clean: "<<node->clean<<endl;
    cout<<"node position: "<<node->position<<endl;
    cout<<"node size: "<<node->size<<endl;
    node->diff = NULL;
}

Output is:

MADE NODE FOR again 
4 node clean: again 
5 node clean: again 
6 node clean: again 
node position: 1739
node size: 6
始终不够 2024-11-11 09:14:32

好吧,我们需要实际查看其中一些代码才能确定,但​​这就是错误告诉您的内容:在某些时候,您正在分配一些会覆盖或删除您的清理的东西。由于您将其声明为 char *,我猜您将其用作指向字符数组的指针,并且一个数组很可能被别名为两个不同单词中的两个“干净”指针。

Okay, we'd need to actually see the code for some of these to be sure, but here's what the bug is telling you: at some point, you're assigning to something that overwrites or deletes your clean. Since y,ou declare it as a char *, I'm guessing you use it as a pointer to an array of characters, and the odds are good that one array is being aliased to two "clean" pointers in two different Words.

小忆控 2024-11-11 09:14:32

除了 new 和 cout 之外,这也可能是 C。

其他一些阅读
C++ 中的结构体和类有什么区别?< /a>
char * 与 std::string< br>
在 C++ 中从 std::string 中删除空格
C++ 字符串的 tolower 函数
如何对 C++ (STL) 中的函子取反?

尝试以下替代方案(未编译的示例)

#include <iostream>
#include <string>
#include <algorithm>
#include <functional>

typedef int SongId;

class Word{
    int position;
    SongId id;
    Word* same;
    Word* diff;

public: 
  const std::string word;

  const int size() const { return clean.length() };

  Word( const std::string& word_, const int position_ = 1739, const int id_ = 0 )
    : clean( cleanse(word_) )
    , position( position_ )
    , id( id_ )
    , same( NULL )
    , diff( NULL )
  {
    cout<<"MADE NODE FOR "<< word_ << "\n"
      <<"node clean: "<< word << "\n"
      <<"node position: "<< position << "\n";
      <<"node size: "<< size() << endl;
  }

  static std::string cleanse( const std::string& dirty)
  {
    string clean( dirty );

// Remove anything thats not alpha num
    clean.erase(remove_if(clean.begin(), clean.end(), std::not1(::isalnum) ), clean.end());
// make it lower case
    std::transform( clean.begin(), clean.end(), clean.begin(), ::tolower);  // or boost::to_lower(str);

    return clean;
  }
};

const char *word = "again ";

int main() {
    Word* node = new Word(word);
}

Aside from new and cout this might as well be C.

Some other reading
What are the differences between struct and class in C++?
char * Vs std::string
Remove spaces from std::string in C++
tolower function for C++ strings
How can I negate a functor in C++ (STL)?

Try the following alternative (uncompiled sample)

#include <iostream>
#include <string>
#include <algorithm>
#include <functional>

typedef int SongId;

class Word{
    int position;
    SongId id;
    Word* same;
    Word* diff;

public: 
  const std::string word;

  const int size() const { return clean.length() };

  Word( const std::string& word_, const int position_ = 1739, const int id_ = 0 )
    : clean( cleanse(word_) )
    , position( position_ )
    , id( id_ )
    , same( NULL )
    , diff( NULL )
  {
    cout<<"MADE NODE FOR "<< word_ << "\n"
      <<"node clean: "<< word << "\n"
      <<"node position: "<< position << "\n";
      <<"node size: "<< size() << endl;
  }

  static std::string cleanse( const std::string& dirty)
  {
    string clean( dirty );

// Remove anything thats not alpha num
    clean.erase(remove_if(clean.begin(), clean.end(), std::not1(::isalnum) ), clean.end());
// make it lower case
    std::transform( clean.begin(), clean.end(), clean.begin(), ::tolower);  // or boost::to_lower(str);

    return clean;
  }
};

const char *word = "again ";

int main() {
    Word* node = new Word(word);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文