【问题标题】:NULL pointer returned by new and malloc, why?new 和 malloc 返回的 NULL 指针,为什么?
【发布时间】:2011-05-24 02:23:57
【问题描述】:
#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 gigs 的 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++,所以我想解决这个环境中的问题...

编辑:下面的代码现在可以工作了。出于某种原因,如果你在第一个 new 中使用括号,它会起作用,但下次你使用 new 时,它就不起作用了!! 如果我将两个新分配都使用 [] 语法,它就可以工作。如果我将第一个新分配与 [] 和第二个与 (),它也可以工作。诡异的。无论如何,从现在开始我将使用 []...谢谢大家。

【问题讨论】:

  • 如果N 控制到达该行但异常的值是多少?
  • 您确定这里没有异常吗? memset(v0, 1, N);
  • 不,它发生在尝试在这里执行 memset 之前。
  • 括号分配单个字符并将值初始化为N。方括号分配一个字符数组。

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


【解决方案1】:

你应该使用

matrice = new char[nbr1 * nbr1];

记得释放

delete[] matrice;

【讨论】:

  • 我们有 boost::arraystd::vector 用于 C++ 中的动态数组,顺便说一句。
  • 你建议我使用 [] 而不是 ()。好的,但它做同样的事情。
  • @toto:嗯,不是吗? new char[n] 分配n 未初始化的字符,而new char(n) 分配一个初始化为值n 的单个字符。
  • @Kos:每个人都建议这样做,但是自从在 Windows 下编写 dll 插件以来,我一直避免使用 STL,因为包括标准库会大大增加 dll 的大小。我想事情可能会有所改善……或者在某些情况下 STL 不合适。
  • @sje397:如果您每次编写函数时都在重新发明轮子,为什么有人要使用您的 dll 而不是使用 stl?这就是它的用途。你永远无法正确管理自己的记忆。
【解决方案2】:

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

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

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

【讨论】:

  • +1 不错的镜头,我看不到这个,我的 C 正在丢失...也许我们应该建议他使用 std::vector 而不是 C 数组...
【解决方案3】:

直接的问题是您使用圆括号而不是方括号。

但使用 std::vector 代替原始数组。它为您进行分配和释放。正确。

干杯&hth.,

【讨论】:

  • 不,括号在分配单个字符时有效。这就是将值传递给构造函数的语法。
  • @Jonathan:wtf。你的意思是“不”吗?以及您的其余评论,是的,确实如此,但是您是否检查过代码关于的内容?
  • 我承认我花了有限的时间研究代码。但我的观点只是以这种方式使用括号是有效的。如果您的观点是他应该分配一个数组而不是单个字符,那么我同意您的看法。我想我只是不认为这是括号的问题。
【解决方案4】:

我无法测试你的代码,但你做了一些不干净

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

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

只是我的小假设。

编辑:我无法测试您的代码,因为我没有您的示例“graphe.txt”...所以我从文件中什么也没读

【讨论】:

  • 我也是这么想的; +1。另外我想补充一点,如果您一直打开警告,可以更轻松地避免此类事情。
  • @Cam 似乎我们都在未初始化整数的噩梦之间犯了错误;-)
  • @toto 好的,这不是问题,但你不应该这样写代码。 尽可能初始化变量。
  • 这就是为什么在下午 2:00 之后编码不好的原因。这是午饭后的时间。最好睡一个小时或拖:)
  • 我还年轻,还在上大学。我选择了 STUDIES + SLEEP 但没有女孩所以我有充足的睡眠谢谢你,即使我在晚上哭了。
【解决方案5】:

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

除此之外,您的问题有点令人困惑。它是返回 null 还是引发异常。同一行不会两者兼得。

【讨论】:

    【解决方案6】:

    我认为你犯了几个错误

    1. 肯定至少有一个小的编码,因为正如 sje397 指出的那样,您分配的是单个字符而不是数组。我希望您知道其中的区别,并且这只是一个错字。

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

    3. 态度非常严肃。当程序出现问题时,99.999% 的问题出在您的代码中。这不是编译器中的错误。这不是操作系统中的错误。这不是有缺陷的RAM。只是您的代码错误,因此您必须搜索并解决问题。保持首先认为问题出在别人的代码中的习惯不会真正让你在编程中走得更远。

    【讨论】:

    • 嘿,你是对的,但我认为你在这里有点粗鲁。如果我喜欢使用纯数组而不是向量,那么这就是我的选择。 vector 在库中, char 在语言中,所以我在做 C++ 好吧。我同意第 3 点。
    • 如果这听起来很粗鲁,我很抱歉,但这是来自我个人经验的建议。在花时间实际学习这门语言之前,我写了很多 C++ 程序,相信我这会产生巨大的影响。如果即使知道 std::vector 也想以这种方式使用原始内存,那肯定是一个选择,例如如果您想使用 malloc(1+strlen(...))/strcpy 而不是 std::string 但有在极少数情况下,这不会是一个错误。您的代码在很多方面确实令人尖叫,您从未花时间阅读任何 C++ 文本。相信我,它真的可以有所作为;试一试。
    猜你喜欢
    • 2013-05-16
    • 2022-01-02
    • 2011-08-24
    • 2017-05-25
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多