new和malloc返回NULL指针,为什么?

时间:2010-12-11 23:14:48

标签: c++ visual-c++ memory-management

#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;
}

所以这是我在笔记本电脑上从2PM开始编码的程序。我使用的是Visual Studio 2008和Windows 7 64位。我正在编码,一切都很顺利。当我尝试测试我的程序时,行:

v0 = new char(N);

给我一​​个例外。我尝试使用malloc和calloc获取内存,我能得到什么?空指针!!我的机器上有4个ram的演出,我无法在这里获得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 ++,我想在这个环境中解决问题......

编辑:以下代码现在有效。出于某种原因,如果你在第一个新的使用括号,它会工作,但下次你使用新的,它将无法正常工作! 如果我使用[]语法放置两个新分配,它就可以工作。如果我将第一个新分配与[]和第二个分配给(),它也可以。奇怪的。无论如何,从现在开始我将使用[] ...谢谢大家。

6 个答案:

答案 0 :(得分:4)

你应该使用

matrice = new char[nbr1 * nbr1];

并记得免费

delete[] matrice;

答案 1 :(得分:4)

您的代码有一个错误的错误:

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

你可能意味着“new char [N]”来分配N个字符。但是你的代码只分配1个字节值N.然后你将内存从V0覆盖到VO + n-1到1.谁知道你在这里覆盖了什么内存。

答案 2 :(得分:3)

当前的问题是您使用圆括号而不是方括号。

但使用std :: vector而不是原始数组。它为你做分配和解除分配。正确。

欢呼&amp;第h。,

答案 3 :(得分:2)

我无法测试您的代码,但您执行的操作不干净

您没有初始化变量int N; 你至少应该写int N =0;

如果你的循环使得N没有按你想要的方式初始化,那么你的N是一个随机整数,可能远远大于你在new使用它时可用的内存。

只是我的小想法。

编辑:我无法测试你的代码,因为我没有你的例子“graphe.txt”......所以我从文件中读不出任何内容

答案 4 :(得分:0)

v0 = new char(N)分配一个值为N的单个字符。您的意思是分配一个数组吗?

除此之外,你的问题有点令人困惑。它是返回null还是引发异常。同一行不会同时做到这两点。

答案 5 :(得分:0)

我认为你犯了几个错误

  1. 肯定至少是一个小编码,因为sje397指出你分配的是一个char而不是一个数组。我希望你知道其中的差异,这只是一个错字。

  2. 使用C ++而不首先阅读任何有关它的更严重的事情(没有人知道C ++会以这种方式使用new ......这是std :: vector的工作)。 C ++不是一种你可以希望通过实验来学习任何体面程度的语言。这很难过,但事实是......在C ++中,当你犯错误时,你会得到可怕的Undefined Behavior怪物,而这并不是一种简单的学习方式;对于C ++来说尤其如此,因为语言在许多领域既复杂又不合逻辑,而且这是因为历史事故(遗产,青年错误,委员会效应)......无论你多么聪明,你都无法做到猜历史:必须研究历史。如果你有兴趣学习C ++那么请帮自己一个忙,选择任何好的C ++书籍并先阅读一下...... C ++是一个非常好用且有力的武器,但它很容易成为你最糟糕的噩梦尝试从错误的一方攻击它。

  3. 态度非常严肃的人。当程序出现问题时,问题出现在您的代码中的次数为99.999%。这不是编译器中的错误。这不是操作系统中的错误。这不是有缺陷的RAM。这只是你的代码错了所以你必须搜索并修复问题。保持首先想到问题出在其他人的代码中的习惯,并不会让你在编程方面走得太远。