C++ 使用双指针,从**void开始投射。(未处理的异常0xC0000005:访问冲突)

C++ 使用双指针,从**void开始投射。(未处理的异常0xC0000005:访问冲突),c++,arrays,pointers,C++,Arrays,Pointers,我正在动态创建一个对象数组(图像对象)。我有一个函数,可以导出指向上述对象的双指针。这个返回被传递给一些不知道我的Image类的代码,所以我将双Image指针转换为双void指针。这段代码稍后将同一个双空指针传递回一些代码中,这些代码知道我的Image类。最后,我将把double void指针重铸回一个double Image指针,并处理对象 问题是我遇到了一个熟悉的错误(未处理的异常0xC0000005) 这里是发生错误的地方- void Game::drawState0(void** vPt

我正在动态创建一个对象数组(图像对象)。我有一个函数,可以导出指向上述对象的双指针。这个返回被传递给一些不知道我的Image类的代码,所以我将双Image指针转换为双void指针。这段代码稍后将同一个双空指针传递回一些代码中,这些代码知道我的Image类。最后,我将把double void指针重铸回一个double Image指针,并处理对象

问题是我遇到了一个熟悉的错误(未处理的异常0xC0000005)

这里是发生错误的地方-

void Game::drawState0(void** vPtr)
{
Image **iptr = (Image**)(vPtr);

(*iptr)[0].doStuff(); //this line blows up
(*iptr)[1].doStuff();
(*iptr)[2].doStuff(); 
} 
奇怪的是,我传递的地址看起来还可以。那么为什么会有访问冲突呢

更新:要求提供的补充资料

UPDATE2:调用drawState0的代码(去掉不相关的位)

渲染的定义:

void Top::renderImage(void** vPtr)
{
render(vPtr);           // call render() in derived object
}
在派生对象中渲染的定义

void Top::render(void** vPtr)
{
switch (var)
{
    case 0:
    {
        drawState0(vPtr); 
        break;
    }
    //....
更新3:创建imgPtr(这是在重铸双指针后将其返回的函数

Image **st0 = new Image*[3];

for (char j = 0; j<= 2; j++)
{
    st0[j] = new Image; 
}

//..
imgPtr = (void**)st0;
return imgPtr;
Image**st0=新图像*[3];

对于(char j=0;j这是一种不可移植的转换:
Image**iptr=(Image**)(vPtr);

void**
不是“通用双指针”。只有
void*
是通用指针

如果您的实现对
Image*
void*
使用相同的大小和表示形式,那么代码可能仍然有效

我猜您在调用
drawState0
时没有正确设置指针。例如,您铸造了一个二维数组。您能显示调用此函数的代码吗


我的建议是重新设计界面,不要使用
void**

不确定我看到了什么,但如果
vPtr
是一个指针数组,我相信它是这样的,那么您应该改为:

iptr[0]->doStuff();
iptr[1]->doStuff();
iptr[2]->doStuff();

对我来说,这看起来像是访问冲突,您的vPtr分配正确吗?请发布一个(简短的)完整的程序,给出例外。通常,如果您只发布程序的一部分,问题总是存在于其他地方的可能性(在这种情况下,似乎是这样),我们只是在浪费时间阅读你的问题。杜克,整个程序只有几个Kline。我通过调试器找到了中断的行。它在原始帖子中有评论。我还附上了一个VS2010屏幕截图,显示了执行错误行之前相关实体的状态。我还能提供什么ide代替了整个程序,这会很有帮助吗?@Dimitrisbouzas什么是“正确分配”意思?监视窗口显示了我希望看到的值。@ooga-这是不正确的。空指针是一个有效的概念,它本身就是一个需要存储在某处的地址。因此,您可以有一个指向存储位置的指针,一个指向空类型的指针,即void**。我将发布您请求的代码。另外,为什么rsion non portable?你能详细解释一下你的最后一句话吗?我不完全确定它的意思。它是不可移植的,因为
void**
必须指向
void*
。当你写
*vPtr
时,你可以访问与此
void*
对应的字节,就好像它是一个
Image*
,这是未定义的行为iour,因为这不是一对定义良好的内存别名类型。它类似于
void foo(double*d){int*bar=(int*)d;}
,当
foo
作为
double x;foo(&x)调用时遇到麻烦
@MattMcNabb最后我们在这里讨论指针,正如你应该知道的,所有指针都有相同的大小和内容。只要他将其转换为正确的类型,输入的类型和转换本身就无关紧要。“所有指针都有相同的大小和内容”-不一定。
sizeof(void*)
sizeof(其他类型*)
可能不同;即使它们相同,也可能有不同的表示形式。@OP,您需要显示创建指针的代码。您的“更新2”仅显示在
update()
函数(可能)创建指针后,指针被复制,而您没有显示
update()的代码
.Wow.这很有效。有什么区别吗?*iptr[0]仍然应该给我一个用于执行doStuff()的对象,对吗?当我这样尝试时,VS2010甚至会为我自动完成“doStuff()”。好吧,你这样做就像
(*iptr)[1]
,因此您使用
iptr
中的第一个元素作为数组,而不是
iptr
本身。这就是您的问题。嗯,我假设如下:1)**iptr是指向图像指针的指针2)*iptr[j]是图像j的地址,这不是真的吗?正如我提到的,当我键入“*iptr[0]”时VS2010对我来说开始自动完成,就好像它是一个目标一样。这都是synthax的问题。
(*iptr)
获取
iptr
中的第一个指针,该指针应该是指向
图像
对象的指针,但是您将其用作
图像
对象的数组。synthax
->
的存在简化了这一点。看起来您出于某种原因试图避免使用
->
,最终您将不要这样做。
(*iptr)[1]。doStuff()
相当于
iptr[0][1]。doStuff()
,而
iptr[1]->doStuff()
相当于
iptr[1][0]。doStuff()
。这就是为什么我很想看看你最初是如何设置指针的。
iptr[0]->doStuff();
iptr[1]->doStuff();
iptr[2]->doStuff();