Почему изменение в заголовке функции может привести к тому, что назначение указателя не будет работать? - PullRequest
0 голосов
/ 05 января 2012

Когда я изменяю последний параметр в заголовке функции с char Findthis[64] на char * Findthis при отладке разрывов назначения Testthis=&*Look_in;. Look_in имеет адрес памяти и значения элементов, но Testthis не назначается это местоположение указателя. Почему это происходит?

struct Node * ProbableMatch(struct Node * Look_in, int MaxNodes,
char Findthis[64])
{
    char Findit[64];
    strcpy_s(Findit,64,Findthis);
    struct Node * CurrentHighProb;
    CurrentHighProb=new(Node);
    struct Node * Testthis;
    Testthis=new(Node);
    Testthis=&*Look_in;

    while((Testthis) || (i!=(ccounter-1)))
{ //This Testthis does not cause exception
    string str1;
    string str2;

    n1=sizeof(Testthis->NAME);
    n2=sizeof(Findit);

    n=0;
    while((Testthis->NAME[n]!='\0') && (n<=n1)){
              //While Testthis->NAME here causes the exception
         if(Testthis->NAME[n]=='-'){Testthis->NAME[n]=' ';} 
        n++;
    }//end of while

// _ РАЗНАЯ ЧАСТЬ ПРОГРАММЫ _ __ _

 std::string Findme;
 cout<<"Enter varible to find. Type quit to quit, case sensative."<<endl;
 cin>>Findme;
 char * writable = new char[Findme.size()+1];
 std::copy(Findme.begin(),Findme.end(),writable);
 writable[Findme.size()] = '\0';

 if((Findme.compare("quit")!=0) ^ (Findme.compare("Quit")!=0) ^ (Findme.compare("QUIT")!=0)){
    ProbableMatch(head,ccounter,writable);
 }

 delete [] writable;

// _ УЗЕЛ _ ___

struct Node 
{   public: 
    int VARID,counter,prob;
    char NAME[64];
    char DESCRIPTION[1024];
    struct Node* next;
}node, *pNode=&node;

Ответы [ 2 ]

0 голосов
/ 07 января 2012

Хорошо, похоже, что преобразование std :: string в char * вызывает утечки.

Переключено на векторную опцию, как предлагается здесь: Как преобразовать std :: string в const char * или char *?

Проблема ушла. Мне нужно будет проследить фактическую память позже, но я нахожу странным, что эта строковая память была помещена прямо рядом с началом связанного списка.

0 голосов
/ 05 января 2012

Больше похоже на C-код. Почему вы используете C-строки и стандартные строки? В любом случае, похоже, что ваша ошибка не связана. Назначение до Testthis = &*Look_in бесполезно (не говоря уже о вызове new утечки памяти). В этом случае нет причин сначала разыменовывать свой узел Look_in, а затем брать адрес. Вы должны иметь возможность просто изменить это утверждение на Testthis = Look_in.

Однако, если это ошибка времени выполнения, убедитесь, что Look_in != NULL или не удален где-то еще.

Похоже, у вас есть небольшая путаница с указателями в целом; так что вот быстрое сокращение.

Указатели указывают на область памяти, в которой хранится некоторое значение. Поэтому, когда вы объявляете указатель и назначаете ему какое-то место в памяти, вы указываете этому указателю, где в памяти искать какой-либо элемент. Когда вы разыменовываете действительный ненулевой указатель, вы можете получить значение, которое содержит это место в памяти. Например,

Node x[64]; // An array of 64 nodes
Node * t = x; // t points to element 0 of x. Therefore, changing values of x changes values of t and changing values of t changes values of x

Кроме того, распределение / освобождение памяти - это отдельная история. Память стека (как указано выше для обоих этих объявлений) управляется операционной системой. Однако распределение кучи зависит от вас (т.е. new / delete).

Node * x = new Node;
// Do stuff with your node - it is on the heap, so it is persistent until you explicitly remove it
delete x;

Самое большое различие между стеком и кучей состоит в том, что память кучи превышает срок службы функции. Например, каждая функция получает свой собственный стековый фрейм для объявления переменных. Однако при выходе из функции стековый фрейм освобождается. Однако в динамической памяти могут храниться значения, которые не являются исключительными для времени жизни одной функции.

Простой пример:

int* giveMeAnInt()
{
  int x;
  return &x;
}

В приведенной выше функции мы объявляем переменную local и пытаемся вернуть ее адрес в качестве указателя на это значение. Однако после того, как мы вернемся, это значение в любом случае вытесняется из стека, так как функция завершилась. Чтобы сделать это правильно, вам необходимо:

int* giveMeAnInt()
{
  int* x = new int;
  return x;
}

Второй пример объявляет переменную в куче и возвращает ее адрес. Но не забывайте, что если вы используете new, вы должны delete позже. Другой быстрый пример (используя рабочую версию кода выше, т.е. пример 2)

...
int * z = giveMeAnInt();
cout<< *z << endl;
delete z; // Free the memory allocated by the giveMeAnInt() function
...

Это много быстрой информации, но удачи.

EDIT

Возможно, если у вас сбой на ...->NAME[n], то NAME[n] не существует. Обратите внимание, что вы эффективно разыменовываете Testthis на sizeof(Testthis->NAME), поэтому проблема не в указателе. Если вы ищете количество символов в строке для указателя, то вы должны использовать strlen(), а не sizeof().

Вот проблема, с которой мы сталкиваемся: разница между массивом и указателем. Если вы объявите char someArray[64], то sizeof(someArray) == 64. Однако, если вы объявляете char* someArray, то sizeof(someArray) == 4 (начиная с sizeof(char*) == 4, предполагая 32-битный компьютер. Но на данный момент константа не имеет значения), а не фактическое количество символов. Чтобы быть в безопасности, вы должны вместо этого просто использовать strlen(someArray), который будет работать, как ожидается, для обоих объявлений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...