2

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

我写了两个简单的类(歌曲和元数据)并用 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 编译器

先感谢您!

问候塞巴斯蒂安

歌曲.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();

};

歌曲.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;
}

元数据.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

元数据.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;
}
4

1 回答 1

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[]and的不正确终止MetaData::albumin[]。不要只修复这两个;把它们都修好

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

于 2012-11-22T18:37:40.900 回答