谁知道malloc_consolidate是个什么函数?

已经两天了,我最终放弃了继续追查原因。毕竟我是研究硬件的,不是研究软件的。不过这个问题还是应该被记录一下。

所有的程序在Intel 32-bit Duo-Core Fedora9 Linux 2.6.27 + GCC 3.4.5下都是正确的,不过一旦同样的源文件,运行在AMD 64-bit Duo-Core SUSE Linux 2.6.16 + GCC 4.1.0下很容易出现segment error(内存错误)。错误有两种,一种是直接报出SIGSEVG之后停止,GDB的堆栈信息:

Program received signal SIGSEGV, Segmentation fault.
0x00002adde5c9940b in malloc_consolidate () from /lib64/libc.so.6
(gdb) bt
#0  0x00002adde5c9940b in malloc_consolidate () from /lib64/libc.so.6
#1  0x00002adde5c9a853 in _int_free () from /lib64/libc.so.6
#2  0x00002adde5c9a99c in free () from /lib64/libc.so.6

可见在释放内存的时候出现了问题。

另外一种是程序运行结束之后,在释放一个类对象的时候,报出一个内部的双向链表被破坏。同样给出栈堆信息,错误也是由malloc_consolidate函数发出。

尽管最终没有找到原因,不过得到以下几点收获。

使用STL的queue和stack确实很方便,但是他们往往是造成这种内存错误的罪魁祸首。由于队列长度不定,在libstdc++的内部实现中使用dque<>容器实现。每添加一个元素(push方法)和弹出一个元素(pop方法)实际上在执行new和delete操作,由linstdc++调用libstdc从而执行malloc和free。由于STL的使用内存操作频繁,内存错误的可能性也加大。如果知道队列的最大长度,可以自己实现一个特别简单的queue和stack泛类,减少内存操作。

stack比queue稳定。至少我没有发现由于stack引发的内存问题,但是一旦queue中的类型是一个自定义的类,就很容易出错。我确定我正确的编写了关于构造、析构、拷贝和赋值的方法。

另外,我个人认为该问题是由于运行在64位CPU的libstdc库的内部问题,而非程序问题。同样的程序,在32-bit的环境下无论用gdb怎么跟都不出问题,但是在64-bit死活不能运行。跟加有效的证明,如果我将32-bit环境下生成的执行程序拷贝到64-bit环境下用兼容方式运行,一切正常。显然只要使用libstdc 32-bit的版本能够解决该问题。网上出现该问题的描述也大多出现在64-bit平台。

另外,附上我自己写的一个简单的queue和stack泛类实现:

#include <stdexcept>                // for debug purpose

template <typename item, unsigned int qsize>
class queue {
public:
    item data[qsize];
    unsigned int rp,wp;
    bool full;

    queue():   rp(0),wp(0),full(false) {}

    bool empty() { return ((rp == wp) && (!full)); }

    unsigned int size() {
        if(!full)   return (wp-rp+qsize)%qsize;
        else        return qsize;
    }

    item& front() {
        if(empty()) throw;
        return data[rp];
    }

    item& back() {
        if(empty()) throw;
        return data[(wp-1+qsize)%qsize];
    }

    void push(const item dd) {
        if(full)    throw;
        data = dd;
        wp = (wp+1)%qsize;
        if(wp == rp)    full = true;
    }

    void pop(){
        if(empty()) throw;
        rp = (rp + 1)%qsize;
        full = false;
    }
};

template <typename item, unsigned int qsize>
class stack
{
public:
    item data[qsize];
    unsigned int p;
    stack():   p(0){}

    bool empty() {  return (p == 0);}
    unsigned int size() { return p; }

    item& top(){
        if(empty()) throw;
        return data[p-1];
    }
    void push(const item dd) {
        if(p==qsize) throw;
        data[p++] = dd;
    }

    void pop() {
        if(empty()) throw;
        p–;
    }
};

Advertisements

Why my life is a mess with joy?

Why my life is always a mess with a joy.

I entered the best high school in the city but needed a special favor because I got a 7 score less than the requirement.

I failed to enter the best university but a master without the entrance exam.

I lose the chance to chase someone but had someone chased me.

I even received the US F1 VISA and the full scholarship from UK exactly at the same day.

This week, I got the rejection of my first paper in UK. You know, the review has more than 500 words, which is really a bomb to me. After reading it, I suddenly find out, my paper should in the trash. I hope I can find a crack on the floor, which I can hide in. But, ridiculously, I receive my first credit card in UK with an amazing 2000 pound limit. Just 6 month before, I failed to apply a 250 pound limited one.

So, why cannot I have just a little bit more normal and peaceful life if considering that I am such this traditional person who totally don’t like shocks!

关于参考文献的一些原则

    很久就想写这么一篇文章,但是一直都没时间动笔,现在有1个小时,想起来了,就写一笔吧。

1. 不要抄袭
国内和国外对什么是抄袭也许定义不一样。在国内受到的教育是,抄了,注上就可以了。但是,在国外,这也是抄袭。我倾向于国外的定义。所以,引用另一篇文章的方法是:
(1)对于观点,需要重新总结,用自己的话,适合自己文章的语言,重新在文章中描述一遍,并注释。
(2)对于数字,需要准确的使用(数据的环境,条件等等),标明来源并注释。
(3)对于一些经典的话,需要引用原文的,需要在文章将原文用用双引号括起来,表明是原文引用。并注明出处。
我个人认为这是正确的。文章应该有自己观点和立场,每一篇论文的观点和立场应该有所不同。所以直接照抄其他论文中的原文,实际上是对论文的一种马虎的态度,并没有深刻考虑被引论文的立场和自己论文的上下文。

2. 引用来源
我自己是学工科的,相信理科有同样的标准,文科其实也差不多。有几点倾向性的原则。
(1)专业论文应该尽量引用专业来源,而不要引用非专业来源。
专业来源的优先级大概如下:
学科较著名的开创性的论文 > 有影响力的期刊的论文 > 有影响力的会议的论文 > 学术著作 > 一般期刊论文 > 会议论文 > 协议/手册/数据库 > 经典教科书 > 一般指导性书籍 > 大众期刊 > 报纸 > 商业期刊 > 网站 > 个人博客
其实,从教科书开始,就不要在学术性的文章中出现了。当然这个先后次序对不同的专业会有区别,但是基本一致。有人认为为何应用教科书不好。如果想到学术论文应该是研究学术前沿的东西,教科书往往是已经公认,已经研究了几十年的成果,引用教科书已经没有重要意义了。
(2)查找引用源应该查找一级出处。
何为一级出处?其实就是根源,最开始发表这一观点的论文。该论文可能被其他论文引用,则引用论文为二级论文。
在引用的时候一定要引用一级出处。原因很简单,只有一级出处才是次观点最真实的表现,其他的二级出处可能掺杂其他作者的立场和观点;只有找到了一级出处才说明作者对该问题做了较深刻的研究;只有引用一级出处才能说明作者真实的对被引者表达敬意(我们都不希望自己的观点算到别人的头上)。
为了做到该点,我们必须阅读所有的被引文献,确保为一级出处,而不要随意的转用其他论文中的引用(很少有人真的做到了,每况日下呀)。另外,不要认为引用名人的二级文献就可以替代一级的出处。虽然名人的影响大,但是这并不是他的原始观点,其他人也会看得很清楚。不要认为原文过于久远就不去查找,不可偷懒。
(3) 引用来源的选择
有时,都是一级出处但是仍然可以选择。比如同时有书,论文,网站,数据库,综述等等。我的观点是这样,有论文一定要引论文,论文往往是最原始的。有研究性论文就不要使用综述,综述往往是二级出处。有论文就不用书,除非书中有很大的改动。有论文和书,网站和数据库就不要考虑了吧。
另外,版本也是个问题。比如书的版本,协议的版本,法律的版本,手册的版本。大概应该是选择较新的,选择大家较公认的,选择可以获得的。
可获得性也需要考虑。有时候真的很沮丧。读一篇论文,发现一个有趣的观点,结果一看出处,是一个会议的邀请报告,或者是一个内部报告,没有出版物的会议。这些出处也许是一级出处,但是除了作者之外,其他人根本就没有办法获得。引用注释的目的就是读者可以参阅,如果别人根本找不到,出处就没有意义了。

3. 引文出处的排列顺序
参照国内和国外较为接受的排序方法。
按出现顺序排序:在文章中先出现的引用先列出处。现在一般的中文杂志都应该是按照此标准。
按照作者的字母顺序:按照作者英文的字母顺序。这种方法一般出现在英文的书籍和毕业论文当中。
按照年代顺序:一般出现在书籍,综述性论文和人文社科类论文中。
建议所有的论文使用出现顺序排序,这是最为接受的,且中英文方法一致。但是,其实国内学生的做法往往没有顺序,经常论文中上来就是一个非[1]的注释。看看注释列表也没有什么顺序。这样只能说是还没有了解论文的基本写作原则。

4. 出处的写法
出处是为了方便读者能够找到原文,所以一切以此原则出发。比如篇论文在一个没有出版物的学术会议上发表,那么最好标注上电子版本的地址,同理适用于内部研究报告。所使用的数据库,手册也应该标注上版本,年代,网址方便查找。书籍应当注明页码,你不会希望读者去读一整本书吧?关于格式,一般的杂志都会给出自己的排版方法,投稿前仔细阅读并修改。需要特别说明的是,参考文献的格式一定要统一。很多人都习惯了用bibtex或其他的工具,直接用各个数据库的参考文献信息。殊不知,各大数据库的写法是不一样。比如说同一个期刊TC,IEEExplorer也许写成了Computers, IEEE Transactions on,而ACM的数据库则写IEEE Trans. on Computers。如果同一篇文章用了两个参考文献都是TC的文章,但一个用IEEExplorer而一个来自ACM,格式就会不一样。所以,即使是数据库来的参考文献信息,也需要手动复查统一格式。

5. 如何准备
一定一定要在写论文之前就开始考虑参考文献的问题,不要论文写完了,为了做做样子再加参考文献。我看见太多这样的例子了,结果都是一眼就能看出参考文献有问题。比如说有的参考文献都是近几年的,出自为数不多的几个来源,出自为数不多的几个人,注释的位置都标在介绍的章节,被注的都是通俗不能再通俗的观点。这样会被嘲笑的。
在写论文之前,把会被使用到的参考文献先准备出来,甚至直接先写上(我就是这样),这样有利于构思论文结构,同时参考文献自然不是后来拼凑上的。然后写论文的时候产能在需要引用的时候合适的找到出处引用上。还是一样,要严谨,不要偷懒。

可能还不够全,想到再补充