【问题标题】:Access violation writing location in C++C ++中的访问冲突写入位置
【发布时间】:2013-03-27 14:17:25
【问题描述】:

第一次写到这里。我已经看到了像我这样的其他几个问题,但无法解决我的问题。我有 4 个课程:歌曲、播放列表、专辑、艺术家。播放列表由一系列歌曲组成。专辑继承了播放列表并具有更多功能,艺术家由专辑数组和其他一些东西组成。

Album(char* _name, Song* songs,int _sales ,int _year,int n):Playlist(songs,n)
    {
        name = new char[strlen(_name)+1];
        strcpy(name,_name);
        salesCount=_sales;
        year = _year;
    };
Playlist::Playlist(Song* _songlist, int n)
{
    if(n > 20)
    {
        cout<<"The number of song must be lesser or equal to 20"<<endl;
        return;
    } 

    SongList = new Song[n];
    for(int i = 0 ; i<n; i++)
    {
        SongList[i] = _songlist[i];
    }
numberOfSongs=n;
}

当我使用这个构造函数创建一个专辑时,我没有任何问题,但是当我尝试创建一个专辑数组时,它由使用这个构造函数创建的专辑组成,我遇到了内存访问冲突。有任何想法吗 ?

好的,所以我稍微更新了我的代码。这是我在 main 方法中尝试做的事情:

Song newSong("My Song", 9, 231),mySong("Your Song", 8 , 180),yourSong("His Song",7,135), herSong("Her Song",8,431);
Song songs[4] = {newSong, mySong,yourSong,herSong};
Album yourAlbum("My Album",songs,200000, 2010, 4);
yourAlbum.PrintInfo(); //<------- WORKS
Album albums[1]; //<------ It calls the deffault constructor of Album and after it gives me //"Source not available"
//When I try to declare it like this Album albums[1] = { yourAlbum } ; it gives me access violation

Artist myArtist("blake", albums);
myArtist.PrintArtistInfo();

【问题讨论】:

  • 你能展示创建数组的代码吗?
  • 使用std::string 代替char*std::vector&lt;Song&gt; 而不是动态分配Song* 数组。它将使生活变得相当简单。还有stackoverflow.com/questions/4172722/what-is-the-rule-of-three
  • sizeof(*_songlist)/sizeof(_songlist) - 这是不对的。
  • 你的 Album 类有默认构造函数吗?
  • @roger_rowland 就这么简单。当我有例如:code专辑a;专辑b;专辑专辑[2] = {a,b}; code 我没有问题,但是当我尝试执行 code'Album myalbum("name", songs,200000,2010); Album albums[1] = {myalbum};code` 时,我遇到了内存访问冲突

标签: c++ arrays pointers sizeof dynamic-arrays


【解决方案1】:
Playlist::Playlist(Song* _songlist) {
    numberOfSongs = sizeof(*_songlist)/sizeof(_songlist);  // <-- THIS
    ...

导致分配给numberOfSongs 的意外(无意义)值,因为它等于:

numberOfSongs = sizeof(Song) / sizeof(Song*);

如果你需要你的函数知道动态分配数组的大小,你应该自己跟踪这个大小并将它传递给这个函数。

还请注意,由于您使用 C++ 进行编程,因此您应该使用该语言提供的功能。您应该使用 std::string 而不是 C 风格的字符串和 STL 容器,例如 std::vector 而不是 C 风格的数组(在 std::vector 的情况下,对象内部包含有关其长度的信息,因此您不会处理这类问题)。

【讨论】:

  • 有趣的是它可以工作。我完全同意std::string,但这是一个大学项目,我们必须练习其他技术。最让我吃惊的是,当我使用这个构造函数创建专辑时,我可以使用该类的所有功能,但我无法将它添加到数组中
  • @user2215925:我不应该写“不工作”,它是如此的误导和混乱。我编辑了我的答案:)
【解决方案2】:

这里的问题是你分配了一个sizeof(*_songlist)/sizeof(_songlist); 元素的数组。

也就是说,您分配的Song 项目数等于用于存储Song 的字节数除以用于存储指针(指向Song)的字节数。这是一个相当无意义的值。

此外,这个数字是一个常数值,它不依赖于您传递给它的数组中的歌曲数量。因此,无论传递什么,此函数的任何运行都将始终分配相同数量的内存。如果此数字大于实际传递的歌曲数,您将在数组之外进行索引,这是未定义的行为。这可以解释你的分段错误。

另一方面,如果您传递的歌曲多于该常量,您将使用适合您分配的数组的歌曲子集初始化您的数组,从而丢失一些数据。要解决这个问题,要么传递一个(对 a)歌曲的 std::vector 的引用,要么添加一个额外的参数,其中包含数组中歌曲的实际数量并将其用作数组的大小。

【讨论】:

  • 我明白了,我只用树歌测试过它,它工作正常。我会把它作为一个值传递,看看会发生什么。
  • 您能否更新您的示例以包括您如何调用播放列表构造函数?
猜你喜欢
  • 1970-01-01
  • 2018-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多