使用sqlite3时内存不足

时间:2012-11-22 18:21:12

标签: c++ sqlite out-of-memory

我刚开始用c ++编程(IDE是CodeBlocks)。

我写了两个简单的类(Song和Metadata)并使用sqlite进行测试。

问题:我的程序似乎内存不足:当我启动程序时,它会立即崩溃,或者sqlite3_open命令返回错误“内存不足”。当我在没有任何其他代码的情况下测试SQLITE函数时,它可以工作!

所以这不起作用:

#include <iostream>
#include "metadata.h"
#include "Song.h"
#include <cstdio>
#include "sqlite3.h"

using namespace std;

int main()
{
    // Without this block it DOES work!
    Metadata* tmpMeta  = new Metadata("Eiffel 65", "Blue", "Europop");
    Song* tmpSong;
    tmpSong = new Song();
    tmpSong->set_metadata(*tmpMeta);
    // end of block

    sqlite3 *db;
    int rc;
    rc = sqlite3_open_v2("test.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
    cout << "Result: " << sqlite3_errmsg(db) << '\n';
    sqlite3_close(db);
    return 0;
}

请参阅随附的歌曲和元数据类。

我不知道如何应对这个错误。

我的环境: - Windows 8,64位 - Code :: Blocks 10.05 - 编译器:GNU GCC编译器

提前谢谢!

问候 塞巴斯蒂安

Song.h:

#include <iostream>
#include <cstring>
#include "metadata.h"

using namespace std;

class Song {
    private:
    Metadata metadata;
    unsigned int iD;
    char filename[400];

    public:
    //Constructors
    Song( Metadata, unsigned int, const char*);
    Song( );

    //Methods
    void set_metadata(Metadata& meta);
    void set_id(unsigned int i);
    void set_filename(const char* f);

    Metadata get_metadata();
    unsigned int get_id();
    const char* get_filename();

};

Song.cpp:

#include <iostream>
#include "Song.h"

using namespace std;

Song::Song(Metadata m, unsigned int id, const char* f) {
    metadata = m;
    iD = id;
    strncpy(filename, f, sizeof(filename)-1);
    filename[sizeof(filename)] = '\0';
}

Song::Song( ) {
    Metadata tmpMeta;
    metadata = tmpMeta;

    iD = 0;
    strncpy(filename, "unknown", sizeof(filename) -1);
    filename[sizeof(filename)] = '\0';
}

void Song::set_filename(const char* f) {
    strncpy( filename, f, sizeof(filename)-1 );
    filename[sizeof(filename)] = '\0';
}

void Song::set_id(unsigned int i) {
    iD = i;
}

void Song::set_metadata(Metadata& meta) {
    metadata = meta;
}

Metadata Song::get_metadata() {
    return metadata;
}

const char* Song::get_filename() {
    return filename;
}

unsigned int Song::get_id() {
    return iD;
}

Metadata.h:

#include <iostream>
#include <cstring>
#ifndef _METADATA_H_
#define _METADATA_H_

using namespace std;
class Metadata {
    private:
    unsigned int trackNumber;
    char artist[20];
    char title[20];
    unsigned int year;
    char genre[20];
    char album[20];

    public:
    Metadata(const char*, const char*, const char*);

    const char* get_artist();
    const char* get_title();
    const char* get_album();
    const char* get_genre();
    unsigned int get_trackNumber();
    unsigned int get_year();

    void set_artist(const char*);
    void set_title(const char*);
    void set_album(const char*);
    void set_genre(const char*);
    void set_year(unsigned int);
    void set_trackNumber(unsigned int);
};

#endif

Metadata.cpp:

#include <iostream>
#include "metadata.h"

Metadata::Metadata(const char* ar, const char* tit, const char* al) {
    trackNumber = 0;
    year = 0;
    strncpy(genre, "unknown", sizeof(genre) -1);
    genre[sizeof(genre)] = '\0';

    strncpy(artist, ar, sizeof(artist) -1);
    artist[sizeof(artist)] = '\0';

    strncpy(title, tit, sizeof(title) -1);
    title[sizeof(title)] = '\0';

    strncpy(album, al, sizeof(album) -1);
    album[sizeof(album)] = '\0';
}

const char* Metadata::get_artist() {
    return artist;
}

const char* Metadata::get_title() {
    return title;
}

const char* Metadata::get_album() {
    return album;
}

const char* Metadata::get_genre() {
    return genre;
}

void Metadata::set_artist(const char* ar) {
    strncpy(artist, ar, sizeof(artist) -1);
    artist[sizeof(artist)] = '\0';
}

void Metadata::set_title(const char* tit) {
    strncpy(title, tit, sizeof(title) -1);
    title[sizeof(title)] = '\0';
}

void Metadata::set_album(const char* al) {
    strncpy(album, al, sizeof(album) -1);
    album[sizeof(album)] = '\0';
}

void Metadata::set_genre(const char* g) {
    strncpy(genre, g, sizeof(genre) -1);
    genre[sizeof(genre)] = '\0';
}

void Metadata::set_trackNumber(unsigned int tn) {
    trackNumber = tn;
}

void Metadata::set_year(unsigned int y) {
    year = y;
}

1 个答案:

答案 0 :(得分:1)

对于初学者:所有您的字符串终止代码在Metadata.cpp和Song.cpp中是错误的:

示例:

strncpy(genre, "unknown", sizeof(genre) -1);
genre[sizeof(genre)] = '\0';

对strncpy()的调用是正确的。硬终结者不是。它应该是:

strncpy(genre, "unknown", sizeof(genre) -1);
genre[sizeof(genre) -1] = '\0';

这会在所有字符串上复制。重新检查他们。它会表现出几种副作用,直到你修复它们为止。考虑到这些对象都是堆分配的,你就会在Song::filename[]MetaData::albumin[]的不当终止时破坏你的堆。不要只修复那两个; 解决所有问题

记住。 sizeof()返回传递的字段的八位字节数。这意味着char field[N];将返回N。如果您已经了解C / C ++,那么您知道数组是从零开始的,因此field[N-1]是最大允许索引。