【问题标题】:My program runs with MSVC and g++ compilers on Windows but not on Linux我的程序在 Windows 上使用 MSVC 和 g++ 编译器运行,但在 Linux 上不运行
【发布时间】:2012-10-10 15:36:45
【问题描述】:

我正在为一项研究任务编写遗传算法。我不是一个非常有经验的 C++ 程序员(因为我是一名数学家),但我管理我的程序在 Windows 环境中使用 MSVC 2008 和 g++ 编译器正确编译和运行(我使用 CygWin 在 Windows 7 上运行 g++)。现在,问题是该程序必须在 Linux 环境中使用 g++ 的集群计算机中运行,但它总是在执行时崩溃(尽管至少它可以正确编译)。我已经解决了明显的细节(如使用 / 而不是 \ 作为文件名),但无法使其在 Linux 上正常运行。

但是,当我在下面评论函数“Cruce”时,程序结束了,尽管它显然没有执行所需的任务。这是这样一个函数的代码,连同它调用的其他函数(唯一的全局变量是BITGEN,它是一个值为30的整数,用于浮点数的格雷码转换):

    void xPC_BLX(double d, const vector<double>& P1, const vector<double>& P2,
    vector<double>& Hijo1, vector<double>& Hijo2, int genes){

    double I, A1, C1;
    int i;

    for (i=0; i < genes; i++)
    {

        I= d * fabs(P1[i]-P2[i]);

        A1=P1[i]-I; if (A1<0) A1=0.0;
        C1=P1[i]+I; if (C1>1) C1=1.0;
        Hijo1[i]= A1 + Rand()*(C1-A1);

        A1=P2[i]-I; if (A1<0) A1=0.0;
        C1=P2[i]+I; if (C1>1) C1=1.0;
        Hijo2[i]= A1 + Rand()*(C1-A1);
        }
    }

/**********************************************************/
/* Itoc and Ctoi translate ints to strings and vice versa */
/**********************************************************/
    unsigned long int Ctoi(char *Cad_ent,  int length){

        int i;      
    unsigned long n;    

    n = (unsigned long) 0;
    for (i=0; i<length; i++)
    {
        n <<= 1;
        n += (*Cad_ent++ - (int) '0');
    }
    return(n);
    }

    void Itoc(unsigned long int n, char *Cad_sal, int length){

        int i;      

        for (i=length-1; i>=0; i--)
        {
            Cad_sal[i] = (char)('0' + (n & 1));
            n >>= 1;
        }
    }


/*****************************************************************/
/* Translations between fixed point ints and reflected Gray code */
/*****************************************************************/

    void Gray(char *Cad_ent, char *Cad_sal, int length){

      int i;
      char last;

       last = '0';
       for (i=0; i<length; i++)
       {
        Cad_sal[i] = (char)('0' + (Cad_ent[i] != last));
        last = Cad_ent[i];
       }
    }

/*************************************************************************/
/* Translations between string representation and floating point vectors */
/*************************************************************************/
    void StringRep(const vector<double> vect, char *Cad_sal, int genes){

        int i;
        unsigned long int n;
        int pos;
        double INCREMENTO;
        static char *tmpstring;
        static int flag = 1;

        if (flag) {
        tmpstring = (char*) calloc (genes*BITGEN,sizeof(char));
        flag = 0;
        }

        pos = 0;
        for (i=0; i < genes; i++)
        {

        INCREMENTO=(1-0)/(pow(2.0, (double) BITGEN) - 1.0);

        n = (int) ((vect[i] - 0) / INCREMENTO + 0.5);

        Itoc(n, tmpstring, BITGEN);
        Gray(tmpstring, &Cad_sal[pos], BITGEN);

        pos += BITGEN;
        }
        Cad_sal[pos] = '\0';

    }

/*****************************************/
    int DistHam(char *Cr_1, char *Cr_2, int genes){

         int i, dist;
         dist=0;

         for (i=0; i<genes*BITGEN; i++) if (Cr_1[i]!=Cr_2[i]) dist++;

         return dist ;
    }

/**********************/
/* CROSS OPERATOR  */
/**********************/

    void Cruce(int& fin, int genes, vector<vector<double> >& POPULATION,
        vector<vector<double> >& CONTROL, double GA_THR)
    {

        int i, j, temp, mom, dad;
        static char *String1, *String2;
        static int flag=1;
        vector<double> newind(genes+1,0), newcont(2,0);


        if (flag) {
        String1 = (char*) calloc (genes*BITGEN,sizeof(char));
        String2 = (char*) calloc (genes*BITGEN,sizeof(char));
        flag = 0;
        }

        vector<int> sample(TAMPOP,0);  
        for (i=0; i < TAMPOP; i++) sample[i] = i;

    for (i=0; i < TAMPOP; i++)
    {
        j = Randint(i,TAMPOP-1);
        temp = sample[j];
        sample[j] = sample[i];
        sample[i] = temp;
    }

    for (i=0; i < TAMPOP; i++) CONTROL[i][0]=0;

    fin=TAMPOP;

    for (i=0; i < TAMPOP/2; i++)
    {
        mom=sample[2*i]; 
        dad=sample[2*i+1];


        StringRep(POPULATION[mom], String1, genes);
        StringRep(POPULATION[dad], String2, genes);


        if (DistHam(String1, String2, genes)/2.0 > GA_THR)
        {

            POPULATION.push_back(newind);

            POPULATION.push_back(newind);

            CONTROL.push_back(newcont);

            CONTROL.push_back(newcont);

            xPC_BLX(1,POPULATION[mom],POPULATION[dad],POPULATION[fin],   
                POPULATION[fin+1], genes);

            CONTROL[fin][0]=1;
            CONTROL[fin+1][0]=1;
            fin=fin+2;  

        }
    }
}

为了找出可能的错误,我已经竭尽全力寻找可能的错误,但徒劳无功。我猜该错误必须与内存问题有关(因为我总是收到分段错误错误),但我不知道它在哪里。 Windows 和 Linux 处理内存的方式应该有一个我不知道的关键区别。有谁能帮帮我吗?

提前致谢!

【问题讨论】:

  • 我认为您应该尝试缩小可能退出的范围。很难说这里发生了什么,从长远来看,您对 calloc 的使用可能会导致您出现问题,具体取决于您要求的数据量和频率。堆栈不是无限的,并且每个平台的行为都不同。
  • @John:事实上,我想问题必须与通过 push_back() 成员调整 POPULATION 和 CONTROL 向量变量的大小有关,因为程序在“Cruce”之外的其他函数上崩溃但是,当这些变量保持其大小时,这不会产生问题...
  • 你能显示调用 Cruce 函数的代码吗?
  • 使用 valgrind 在 Linux 下运行你的应用程序,这个工具会告诉你你做错了什么。
  • 另一个问题是long在Windows中是32位类型,而在Linux中是64位类型

标签: c++ windows linux memory g++


【解决方案1】:

我在提供的代码中看到了一个潜在的错误。

    static char *tmpstring;
    static int flag = 1;

    if (flag) {
        tmpstring = (char*) calloc (genes*BITGEN,sizeof(char));
        flag = 0;
    }

如果函数StringRep() 被多次调用并使用不断增长的genes 参数会发生什么:缓冲区不会增长,因此,有人将在分配的第一个缓冲区之外写入。注意,同样适用于函数Cruce()

然后我认为关于fin=TAMPOP; 的第二个错误。没有解释什么是TAMOP。但是当你做POPULATION[fin+1]CONTROL[fin+1][0]=1;fin=fin+2; 时,你不是在数组之外吗?

问候。

【讨论】:

    【解决方案2】:

    一些可能对您有所帮助的一般提示:

    • 使用-Wall -Wextra 选项编译为g++ 并改进您的源代码,直到所有警告都消失

    • 尝试使用clang++ 编译器同时使用-Wall(或类似)选项进行编译

    • 使用-g 选项(除了-Wall)进行编译以获取调试信息

    • 使用gdb调试你的程序(并在调试器下运行程序,然后使用bt进行回溯等...)

    • 使用valgrind 查找内存泄漏

    • 避免使用callocmalloc,最好使用标准C++容器(如std::stringstd::vector&lt;&gt;std::map&lt;&gt;等)。

    另外,在您自己的笔记本电脑或台式机上安装 Linux 发行版,并通过命令行学习使用 Linux。

    【讨论】:

    • 我建议通过 Virtualbox 之类的工具安装 Linux 发行版,它允许您在两个平台上共享源代码并同时测试两者。
    • 使用原生 linux 发行版,您可以拥有例如你的 /home 在单独的 Ext3 分区上,并使用 fs-driver.org 与 Windows 共享它
    • 这仍然需要非常频繁重启,此时虚拟机可以与主机操作系统共存。
    猜你喜欢
    • 2019-03-12
    • 1970-01-01
    • 2016-02-25
    • 1970-01-01
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    • 1970-01-01
    相关资源
    最近更新 更多