NULL указатель, возвращаемый new и malloc, почему? - PullRequest
2 голосов
/ 12 декабря 2010
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>

using namespace std;

void multiplier_matrice_vecteur (char * v0, char * A, int N)
{
    int i,j,k;
    char somme;

    for (i = 0; i < N; i++) //On fait N calculs car c'est une matrice 1xN
    {
        //On fait N additions + multiplications
        somme = 0;
        for (j = 0; j < N; j++)
        {
            somme += v0[i] * A[i * N + j];
        }
        v0[i] = somme;
    }
}

int main(void)
{
    bool premiereLignefaite = false;
    //Lire le fichier
    FILE * graphe = fopen("graphe.txt", "r");
    //Fichier de sortie
    FILE * resultat = fopen("resultat.txt", "w");
    int nbr1, nbr2;
    int N;
    char *matrice; //pointeur vers la matrice d'adjacence

    //Ligne lue
    static char ligne[50];

    while (fgets(ligne, 50, graphe) != NULL) //retourne 0 quand on a end-of-file
    {
        //La premiere ligne est différente
        if (premiereLignefaite == false) {
            //Initialiser une matrice d'adjacence NxN
            sscanf(ligne, "%d %d", &nbr1, &nbr2);
            N = nbr1;
            matrice =  new char(nbr1 * nbr1); //Memoire dynamique pour la matrice dadjacence n x n
            memset(matrice, 0, nbr1*nbr1);
            premiereLignefaite = true;
            continue;
        }
        //On construit notre matrice d'adjacence
        sscanf(ligne, "%d %d", &nbr1, &nbr2);
        matrice[nbr1 * N + nbr2    ] = 1;
    }

    printf("Matrice d'adjacence %dx%d : \n", N, N);
    //Affichage de la matrice d'adjacence
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            printf("%c ", matrice[i * N + j] + '0');
        }
        printf("\n");
    }

    //Application de l'algo étapes par étapes
    double tolerance = 0.00001; //Niveau de tolérance de la méthode
    char * v0; //vecteur propre taille N
    char * v; //vecteur tampon
    int valeur; //valeur propre
    int valeur_tamp; //valeur propre tampon

    //Initialiser v0
    v0 = new char(N);
    memset(v0, 1, N);

    //Initialiser A (déja fait)
    //Initialiser tolérance (deja fait)

    valeur = 0;
    while (1)
    {

        valeur_tamp = valeur;
        //Multiplication du vecteur par la matrice
        multiplier_matrice_vecteur(v0, matrice, N);
    }

    //Désallocation de la mémoire
    delete matrice;

    //Fermeture des fichiers etc
    fclose(graphe);
    fclose(resultat);

    return 0;
}

Так что это программа, которую я кодирую с 2 вечера на моем ноутбуке. Я использую Visual Studio 2008 и Windows 7 64 бит. Я кодирую, все идет хорошо. Когда я пытаюсь проверить мою программу, строка:

v0 = new char(N);

Дает мне исключение. Я пытаюсь получить свою память с помощью malloc и calloc, и что я получу? Нулевой указатель !! У меня на машине 4 гигабайта оперативной памяти, и я никак не могу получить 9 байт памяти здесь. Я вообще этого не понимаю.

Для тех, кто имеет Visual Studio 2008 и хочет протестировать в той же среде, вам понадобится файл graphe.txt, вот этот файл:

9 20
0 1
0 2
1 0
1 2
1 3
1 5
2 0
2 1
2 3
3 1
3 2
3 4
4 3
5 1
5 6
5 7
6 5
6 8
7 5
8 6

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

Мне нужно попробовать GCC, но, поскольку я всегда использую Visual C ++, я хочу решить проблему в этой среде ...

РЕДАКТИРОВАТЬ: следующий код теперь работает. По какой-то причине, если вы используете скобки в первом новом, он будет работать, но в следующий раз, когда вы используете новый, он не будет работать !! Если я добавлю оба новых размещения с синтаксисом [], это сработает. Если я добавлю первое новое выделение с помощью [], а второе с помощью (), это также сработает. WEIRD. В любом случае, теперь я буду использовать [] ... Спасибо всем.

Ответы [ 6 ]

4 голосов
/ 12 декабря 2010

Ваш код содержит ошибку:

//Initialiser v0
v0 = new char(N);
memset(v0, 1, N);

Вы, вероятно, имеете в виду «новый символ [N]» для выделения N символов. Но ваш код выделяет только 1 байт со значением N. Затем вы перезаписываете память с V0 на VO + n-1 на 1. Кто знает, какую память вы здесь перезаписываете.

4 голосов
/ 12 декабря 2010

Вы должны использовать

matrice = new char[nbr1 * nbr1];

и не забудьте освободить с

delete[] matrice;
3 голосов
/ 12 декабря 2010

Непосредственной проблемой является использование круглых скобок вместо квадратных скобок.

, но используйте std :: vector вместо необработанных массивов.это делает распределение и освобождение для вас.правильно.

ура и hth.,

2 голосов
/ 12 декабря 2010

Я не могу проверить ваш код, но вы что-то делаете не очищается .

Вы не инициализируете свою переменную int N; Вы должны хотя бы написать int N =0;

если в любом цикле указано, что N инициализируется не так, как вам нужно, то ваш N - это случайное целое число, которое может быть намного больше, чем объем доступной памяти при использовании его с new.

Просто мое маленькое предположение.

РЕДАКТИРОВАТЬ: я не могу проверить ваш код, потому что у меня нет примера вашего "graphe.txt" ... поэтому я ничего не читаю из файла

0 голосов
/ 12 декабря 2010

Я думаю, что вы сделали несколько ошибок

  1. Наверняка хотя бы маленький код, потому что, как указал sje397, вы выделяете один символ, а не массив. Я надеюсь, что вы знаете разницу, и это была только опечатка.

  2. Довольно серьезное использование C ++ без предварительного прочтения (никто не знает, что C ++ будет использовать new таким образом ... это работа для std :: vector). C ++ - это не тот язык, который вы можете надеяться выучить в любой приличной степени, просто экспериментируя. Это печально, но это факт ... в C ++, когда вы совершаете ошибки, вы получаете страшного монстра с неопределенным поведением, и это не простой способ учиться; это также особенно верно для C ++, потому что язык сложен и нелогичен во многих областях, и именно так происходит из-за исторических происшествий (наследие, ошибки молодежи, влияние комитета) ... независимо от того, насколько вы умны, вы не сможете угадать историю: история должна быть изучена. Если вы заинтересованы в изучении C ++, пожалуйста, сделайте себе одолжение и выберите любую хорошую книгу по C ++ и начните сначала с небольшого прочтения ... C ++ - это очень хорошее и мощное оружие, но оно может легко стать вашим худшим кошмаром, если вы попробуйте атаковать его не с той стороны.

  3. ОЧЕНЬ серьезный с отношением. Когда в программе возникает проблема, тогда 99,999% случаев проблема в ВАШЕМ коде. Это не ошибка в компиляторе. Это не ошибка в ОС. Это не дефектная RAM. Это просто ваш код, который является неправильным, поэтому вы должны найти и исправить проблему. Если вы сначала будете думать, что проблема в чьем-то коде, то это далеко не продвинет вас в программировании.

0 голосов
/ 12 декабря 2010

v0 = новый символ (N) выделяет один символ со значением N. Вы хотели выделить массив?

Кроме того, ваш вопрос немного сбивает с толку. Возвращает ли оно значение null или вызывает исключение. Одна и та же строка не сделает обоих.

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