【问题标题】:can not understand this SEGFAULT [closed]无法理解这个 SEGFAULT [关闭]
【发布时间】:2015-04-05 23:49:03
【问题描述】:

我正在编写一个 c/c++ SDL 合成器,它可以在 linux、windows 和处理 psp 上运行,并且我在代码的多个部分中混合了 c/c++。 我使用 new/malloc,但我认为我不会混淆它们,但如果我这样做了,请告诉我在哪里以及为什么。

我的主程序现在接近 20 000 行,并且运行良好。 但是当我开始修改它时,我总是陷入一个错误,我无法理解和发现我真正的错误。

当我开始修改我的代码的某些部分时,我陷入了 SIGSEV,我花了几个小时才使它工作,却不明白我为什么会陷入这种情况。 经过一些修改后它再次工作,我不知道为什么我有一个 SIGSEV 以及为什么它现在被修复以及我如何修改它以使其工作并防止未来的错误。 所以我请你解释一下我真正的错误是什么。

这是一个 gdb 日志,其中包含一个真正精简的版本和我遇到的那种崩溃:

    yoyz@yoyz-laptop:~/build/audio/picoloop/tmp/ gdb ./WaveTable 
    GNU gdb (GDB) 7.4.1-debian
    Copyright (C) 2012 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later         <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show         copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from         /home/yoyz/build/audio/picoloop/tmp/WaveTable...done.
    (gdb) r
    Starting program: /home/yoyz/build/audio/picoloop/tmp/WaveTable 
    warning: the debug information found in "/lib64/ld-2.13.so" does not         match "/lib64/ld-linux-x86-64.so.2" (CRC mismatch).

    Generator::init() Allocating memory
    Generator::one() 0x00604010
    Generator::sine() 0x00604010
    Generator::saw() 0x00604010
    Generator::pulse() 0x00604010

    Program received signal SIGSEGV, Segmentation fault.
    _int_malloc (av=0x7ffff7639e40, bytes=32768) at malloc.c:4738
    4738    malloc.c: No such file or directory.
    (gdb) 

这是代码的精简版:

    #include "MyMaster.h"
    #include "Generator.h"
    #include "WaveTable.h"
    #include "WaveTableManager.h"


    int main(int argc,char **argv)
    {
      Generator G;
      WaveTableManager & WTM = WaveTableManager::getInstance();
      WaveTable* WT;

      G.init();


      WT = new WaveTable();
      WT->setSize(WAVETABLE_SIZE);
      G.one();
      memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
      WTM.insert(WT,PICO_WAVETABLE_ONE);


      WT = new WaveTable();
      WT->setSize(WAVETABLE_SIZE);
      G.sine();
      memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
      WTM.insert(WT,PICO_WAVETABLE_SINE);



      WT = new WaveTable();
      WT->setSize(WAVETABLE_SIZE);
      G.saw();
      memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
      WTM.insert(WT,PICO_WAVETABLE_SAW);


      WT = new WaveTable();
      WT->setSize(WAVETABLE_SIZE);
      G.pulse();
      memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
      WTM.insert(WT,PICO_WAVETABLE_PULSE);


      WT = new WaveTable();
      WT->setSize(WAVETABLE_SIZE);
      G.triangle();
      memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
      WTM.insert(WT,PICO_WAVETABLE_TRGL);


      WT = new WaveTable();
      WT->setSize(WAVETABLE_SIZE);
      G.noise();
      memcpy(WT->getBuffer(),G.getBuffer(),WAVETABLE_SIZE*DEFAULTBITRATE/8);
      WTM.insert(WT,PICO_WAVETABLE_NOISE);


      printf("wavetablemanager.getSize : %d\n",WTM.getSize());

    }

MyMaster.h

    #ifndef __MASTER____
    #define __MASTER____
    #include <SDL/SDL.h>
    #define WAVETABLE_SIZE  1024*16
    #define DEFAULTBITRATE   16

    enum 
      {
        PICO_WAVETABLE_SINE,
        PICO_WAVETABLE_SAW,
        PICO_WAVETABLE_PULSE,
        PICO_WAVETABLE_TRGL,
        PICO_WAVETABLE_NOISE,
        PICO_WAVETABLE_ONE,
        PICO_WAVETABLE_SIZE
      };

    #endif

生成器.h

    using namespace std;

    #include <SDL/SDL_types.h>
    #include <math.h>
    #include "MyMaster.h"

    #ifndef __GENERATOR__
    #define __GENERATOR__

    class Generator 
    {
    public:
      Generator();
      ~Generator();
      void init();
      void sine();
      void saw();
      void pulse();
      void triangle();
      void noise();
      void one();
      Sint16 * getBuffer();

     private:
      Sint16 * table;
      int      table_size;
      int      index;
      int      d;

    };
    #endif

生成器.cpp

    #include "Generator.h"

    Generator::Generator()
    {
      table_size=WAVETABLE_SIZE;
    }

    Generator::~Generator()
    {
    }

    void Generator::init()
    {
      if (table_size>0)
        {
          printf("Generator::init() Allocating memory\n");
          table=(Sint16*)malloc(sizeof(Sint16)*table_size);
          if (table==0)
            {
              printf("Error allocating memory\n");
              //return 0;
            } 
        }   
    }   

    void Generator::sine()
    {
      int i;
      float f;
      Sint16 s;
      Sint16 bitdepth=16-1;
      printf("Generator::sine() 0x%08.8X\n",table);
      for (i=0;i<table_size;i++)
        {
          s=sin((2*3.14159*i*1)/table_size)*(1<<bitdepth-2);
          table[i]=s;
          //printf("table[%d]=%d\n",i,s);
        }
    }

    void Generator::saw()
    {
      int i;
      float f;
      Sint16 s;
      Sint16 bitdepth=16;
      Sint16 dec;

      printf("Generator::saw() 0x%08.8X\n",table);

      s=(1<<(bitdepth-2));
      dec=(1<<(bitdepth-2))/(table_size/2);

      for (i=0;i<table_size;i++)
        {
          table[i]=s;
          s=s-dec;
        }
    }

    void Generator::pulse()
    {
      int i;
      float f;
      Sint16 s;
      Sint16 bitdepth=16;
      Sint16 dec=(1<<(bitdepth-2))/(table_size/2);

      printf("Generator::pulse() 0x%08.8X\n",table);

      for (i=0;i<table_size/2;i++)
        {
          table[i]=((1<<(bitdepth-2))/2);
        }
      for (i=table_size/2;i<table_size;i++)
        {
          table[i]=((1<<(bitdepth-2))*-1)/2;
        }
    }

    void Generator::triangle()
    {
      int i;
      float f;
      Sint16 s=0;
      Sint16 bitdepth=16;
      Sint16 dec=(1<<(bitdepth-2))/(table_size/4);

      printf("Generator::triangle() 0x%08.8X\n",table);

      //table=(Sint16*)malloc(sizeof(Sint16)*table_size);
      for (i=0;i<(table_size*1)/4;i++)
        {
          table[i]=s;
          s=s+dec;
        }
      for (i=(table_size*1)/4;i<(table_size*3)/4;i++)
        {
          table[i]=s;
          s=s-dec;
        }
      for (i=(table_size*3)/4;i<table_size;i++)  
        {
          table[i]=s;
          s=s+dec;
        }
    }


    void Generator::noise()
    {
      int i;
      float f;
      Sint16 s;
      Sint16 bitdepth=16;

      printf("Generator::noise() 0x%08.8X\n",table);

      srand(1<<(bitdepth-2));
      for (i=0;i<table_size;i++)
        {
          if (rand()%2==0)
            table[i]=rand()%8192;
          else
            table[i]=(rand()%8192)*-1;
        }
    }

    void Generator::one()
    {
      int i;
      float f;
      Sint16 s;
      Sint16 bitdepth=16;

      printf("Generator::one() 0x%08.8X\n",table);

      for (i=0;i<table_size;i++)
        {
          table[i]=1<<bitdepth-1;
        }
    }



    Sint16 * Generator::getBuffer()
    {
      return table;
    }

WaveTable.h

    #include "MyMaster.h"
    #include <SDL/SDL_types.h>
    #ifndef __WAVETABLE__
    #define __WAVETABLE__

    class WaveTable
    {
     public:
      WaveTable();
      ~WaveTable();

       int      setSize(int bufferSize); 
       int      allocMemory();
       int      freeMemory(); 


      Sint16 * getBuffer();
      char   * getName();
      Sint32   getSize();



     private:
      Sint32   size;
      Sint16 * buffer;
      char   * name;

    };

    #endif

WaveTable.cpp

    #include "WaveTable.h"
    using namespace std;

    WaveTable::WaveTable()
    {
      size=0;
      buffer=0;
      name=0;
    }

    WaveTable::~WaveTable()
    {
    }


    int WaveTable::allocMemory()
    {
      if (size>0)
        {
          buffer=(Sint16*)malloc(sizeof(Sint16)*size);
          if (buffer==0)
            {
              printf("Error allocating memory\n");
              return 0;
            }
        }
      return size;
    }


    int WaveTable::freeMemory()
    {
      if (buffer!=0)
        {
          free(buffer);
          buffer=0;
        }
    }

    int WaveTable::setSize(int bufferSize)
    {
      if (bufferSize>=0)
        size=bufferSize;

      if (buffer!=0)
        this->freeMemory();
      return this->allocMemory();
    }

    Sint16 * WaveTable::getBuffer()
    {
      return buffer;
    }

WaveTableManager.h

    using namespace std;

    #include <vector>
    #include "WaveTable.h"

    #ifndef __WAVETABLEMANAGER__
    #define __WAVETABLEMANAGER__

    class WaveTableManager 
    {
    private:

      WaveTableManager();
      ~WaveTableManager();

      vector<WaveTable*> wtvector;  

      int    size;


    public:
      static WaveTableManager& getInstance();

      int         getSize();
      void        insert(WaveTable * WT,int position);
      WaveTable * get(int position);


    };
    #endif

WaveTableManager.cpp

    #include "WaveTableManager.h"

    WaveTableManager::WaveTableManager() : wtvector()
    {
      size=0;
    }


    WaveTableManager::~WaveTableManager()
    {

    }



    WaveTableManager& WaveTableManager::getInstance()
    {
      static WaveTableManager instance;
      return instance;
    }


    int WaveTableManager::getSize()
    {
      return wtvector.size();
    }

    void WaveTableManager::insert(WaveTable * WT,int position)
    {
      if (wtvector.size()<=position)
        wtvector.resize(position);
      wtvector[position]=WT;
    }


    WaveTable * WaveTableManager::get(int position)
    {
      return wtvector[position];
    }

Makefile.WaveTable

    CC=g++

    CFLAGS=-O0 -DLINUX -D__RTAUDIO__ -DLINUX_DESKTOP -I. -LSDL/lib -g -fpermissive
    SOURCES=WaveTableTest.cpp WaveTable.cpp WaveTableManager.cpp Generator.cpp
    OBJECTS=$(SOURCES:.cpp=.o)
    EXECUTABLE=WaveTable

    all: $(SOURCES) $(EXECUTABLE)

    $(EXECUTABLE): $(OBJECTS)
            $(CC) $(LDFLAGS) $(OBJECTS) -o $@

    .cpp.o:
            $(CC) -c $(CFLAGS) $< -o $@

    clean:
            -rm -f $(OBJECTS) $(EXECUTABLE)

【问题讨论】:

  • 很难相信你不能产生一个导致这个问题的更小的程序。
  • 如果您删除了所有代码并概括地描述了问题(在malloc 中有很多malloc/free 函数segfaulting 的代码),您会得到有用的答案,并询问有关的一般提示如何排除故障。 (提示,valgrind。)
  • I use new/malloc and I don't think I mix them up but if I do please tell me where and why. 我的问题只是“为什么?”
  • My main program is now near 20 000 line and it works fine. 那么为什么会出现问题呢? But I allways fall into a bug when I began to modify it 这意味着您声称“工作正常”的程序中可能存在现有错误。
  • @Drew :我可以在更少的行上生成它,但 400 行是可读的

标签: c++ linux segmentation-fault g++


【解决方案1】:

这里有一个问题:

void WaveTableManager::insert(WaveTable * WT,int position)
{
  if (wtvector.size()<=position)
    wtvector.resize(position);
  wtvector[position]=WT;  // < -- Out of bounds access
}

当您调用resize() 时,上限为vector::size()-1。由于position 是向量的新大小,您可能想要的是这样的:

  wtvector[position - 1] = WT;  

【讨论】:

  • 这是一个很棒的发现,尽管像这样奖励懒惰的问题可能会对 SO 产生不好的连锁反应。
  • @DrewDormann 我猜这就是投入太多工作的风险。
  • @PaulMcKenzie 谢谢你很快就发现了!!!
  • @yoyz2k 如果解决了问题,你可以点赞,
  • 我不能...这是我在 StackOverflow 上的第一篇文章。我需要 15 的声望来提升这个回复。我要感谢你的帖子。
猜你喜欢
  • 1970-01-01
  • 2018-09-10
  • 1970-01-01
  • 2015-03-11
  • 1970-01-01
  • 1970-01-01
  • 2019-11-10
  • 2016-01-16
  • 1970-01-01
相关资源
最近更新 更多