使用模板作为参数的奇怪段错误

时间:2014-10-30 15:51:08

标签: c++ segmentation-fault valgrind

我有一个排序列表,它将Comparator作为参数。在单元测试中,我尝试使用两种不同的比较器。

奇怪的是,使用StringReverseComparator禁用两个if语句(已注释掉),一切正常,valgrind不会声明任何错误。

template<typename T> class Comparator {
public:
  virtual int compare(const T * left, const T * right) = 0;
  };


class StringReverseComparator : public Comparator<String> {
public:
  int compare(const String *left, const String *right) {
    int rv = strcasecmp((const char *)*left, (const char *)*right);

    if (rv < 0) return 10;
    if (rv > 0) return -10;

    return rv;
    }
};


class StringComparator : public Comparator<String> {
public:
  int compare(const String *left, const String *right) {
    return strcasecmp(left->operator const char*(), right->operator const char*());
    }
};

一旦我启用了两个if语句,我就会从sort方法中获得段错误。 排序方法是sedgewick的标准qsort。

const char *是来自String类的运算符,用于访问字符数组。

首先我想,改变比较器可能会引起麻烦,所以我创建了一个新的排序列表实例。但是,只要我启用了两个if语句,它就会陷阱。

那么比较方法有什么问题?

//编辑:

好的,首先是排序代码(取自sedgewick):

template<typename T> class SortedList {
public:
  // rest omitted

protected:
  void sort() { qsort(0, _size - 1); }
  void qsort(int left, int right) {
    if (right > left) {
       const T *v = _elements[right], *tmp;
       int i = left-1;
       int j = right;

       for (;;) {
           while (_comparator->compare(_elements[++i], v) < 0) ;
           while (_comparator->compare(_elements[--j], v) > 0) ;
           if (i >= j) break;

           tmp = _elements[i];
           _elements[i] = _elements[j];
           _elements[j] = tmp;
           }
       tmp = _elements[i];
       _elements[i] = _elements[right];
       _elements[right] = tmp;
       qsort(left, i-1);
       qsort(i+1, right);
       }
  }

private:
  int               _size;
  const T         **_elements;
  Comparator<T>   *_comparator;
};

...这里是operator char *

顺便说一句:String类传递了所有单元测试,并且对valgrind也没问题。

class String {
public:
    // rest omitted

  operator const char   * () const { return _s; }
  const char * operator * () const { return _s; }

private:
  char    *_s;
};

关于strcasecmp的用法:我的第一次尝试是:

return strcasecmp( ... ) * (-1);

使用与StringComparator中相同的参数。当失败时,我尝试了任何我能想象到的东西,包括operator char *的if语句和不同的调用语法。 strcasecmp不会返回-1,0,1 - 正如许多教程中所提到的那样。返回值的大小和符号不同,在-1,0,1之后失败,我尝试使用10.值没有意义,可能是815或42,无论如何。

// edith 2

谢谢大家的关注!

我自己解决了。关键是,qsort算法不安全enuf :(

以下排序代码可以正常工作(使用任何类型的比较器):

void qsort(int left, int right) {
  if (right > left) {
     const T *v = _elements[right], *tmp;
     int i = left-1;
     int j = right;

     for (;;) {
         while (++i < _size && _comparator->compare(_elements[i], v) < 0) ;
         while (--j > 0 && _comparator->compare(_elements[j], v) > 0) ;
         if (i >= j) break;

         tmp = _elements[i];
         _elements[i] = _elements[j];
         _elements[j] = tmp;
         }
     tmp = _elements[i];
     _elements[i] = _elements[right];
     _elements[right] = tmp;
     qsort(left, i-1);
     qsort(i+1, right);
     }
}

感谢。

0 个答案:

没有答案