简体   繁体   English

Borland C ++ Builder LoadFromResourceID导致违反EAccess

[英]Borland C++ Builder LoadFromResourceID Results in EAccess Violation

I'm using Borland C++Builder 5 to write a game program. 我正在使用Borland C ++ Builder 5编写游戏程序。 I'm trying to load a bitmap from a resource file I created. 我正在尝试从我创建的资源文件中加载位图。 I cannot get the bitmap to load from the resource file either by ID or by Name. 我无法通过ID或Name从资源文件中加载位图。 It will load from file, but I want to use the resource file. 它将从文件加载,但是我想使用资源文件。 Loading from ID or Name results in the following error message at runtime: 从ID或Name加载会在运行时导致以下错误消息:

Project HoldemProbs.exe raised exception class EAcessViolation with message 'Access violation at address 0043F66E in module 'HoldemProbs.exe'. 项目HoldemProbs.exe在模块'HoldemProbs.exe'中引发了异常类EAcessViolation,消息为“地址0043F66E上的访问冲突”。 Read of address 000003EB. 读取地址000003EB。 Process stopped. 进程已停止。 Use Step or Run to continue. 使用“步骤”或“运行”继续。

I'm pretty new to C++ and C++Builder, and I am sure I am doing something wrong. 我对C ++和C ++ Builder还是很陌生,我确信自己做错了什么。 I just can't figure out what. 我只是不知道是什么。 I think it probably has something to do with the HInstance value, but I don't know what. 我认为它可能与HInstance值有关,但我不知道是什么。

Below are relevant pieces of code: 以下是相关的代码段:

ResRC.h ResRC.h

#ifndef RESRC_H 
#define RESRC_H
#define RC_REDBACK 1000
#endif

RedBack.rc RedBack.rc

RC_REDBACK BITMAP "<MYSOURCEPATH>\RedBack.bmp"

HoldemProbs.cpp HoldemProbs.cpp

#include <vcl.h>
#pragma hdrstop
USERES("HoldemProbs.res");
USEFORM("..\Source\HoldemCalc.cpp", Form1);
USERES("..\Source\RedBack.res");

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    try
    {
        Application->Initialize();
        Application->Title = "HoldemEval";
        Application->CreateForm(__classid(TForm1), &Form1);
        Application->Run();
    }
    catch (Exception &exception)
    {
        Application->ShowException(&exception);
    }
    return 0;
}

HoldemCalc.cpp HoldemCalc.cpp

#include <vcl.h>
#include <cstring.h>
#include <HoldemEval.hpp>
#include <Graphics.hpp>
#pragma hdrstop
#pragma resource "*.dfm"
#include <Graphics.hpp>
#include <ResRC.h>
#include "HoldemCalc.h"
#include <string>

#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    CardBackTst();               //Run test of card back bitmap useage
}

CardBackTst.cpp CardBackTst.cpp

void CardBackTst(void){
    Graphics::TBitmap* RedBack = new Graphics::TBitmap;
    Form1 -> Debug -> Text = DEBUGTEXT;     //See below for DEBUGTEXT
    RedBack -> LoadFromResourceID ((ARG1),RC_REDBACK); //See below for ARG1                      
}

There is an Edit Box called Debug used to display debug information. 有一个称为“ Debug的编辑框,用于显示调试信息。 At various times, DEBUGTEXT has been (w/o surrounding " s): 在不同的时间, DEBUGTEXT一直( DEBUGTEXT包含" s”):

"(int)(GetModuleHandle(NULL)"
"reinterpret_cast<int>(HInstance)"
"(int)HInstance"
"(int)(GetModuleHandle("<MYFINALPATH>\\HoldemProbs.exe"))"   // ANSI string
"RC_REDBACK"                     (This yielded the correct value -- 1000)     
"reinterpret_cast<int>(RedBack -> Handle)"
"(int)(Form1 -> Handle)"

At various times, ARG1 has been each of the above values of DEBUGTEXT , except for RC_REDBACK . 在不同的时间,除了RC_REDBACK之外, ARG1都是上述DEBUGTEXT每个值。 All have resulted in an EAccessViolation error. 所有这些都导致了EAccessViolation错误。

The following statement to load from the resource name has been used with each ARG1 value, with the same EAcessViolation result: 以下从资源名称加载的语句已与每个ARG1值一起使用,并具有相同的EAcessViolation结果:

RedBack -> LoadFromResourceName ((ARG1),"MYPATH\\RedBack.bmp"); 

However, the following LoadFromFile() statement to load from the actual bitmap file does work: 但是,以下从实际位图文件加载的LoadFromFile()语句可以正常工作:

RedBack -> LoadFromFile("MYPATH\\RedBack.bmp");

I see two problems with this code: 我看到此代码有两个问题:

  • RedBack.rc does not have a #include "ResRC.h" statement: RedBack.rc没有#include "ResRC.h"语句:

     #include "ResRC.h" // <-- add this! RC_REDBACK BITMAP "<MYSOURCEPATH>\\RedBack.bmp" 

    Without that, RC_REDBACK will not be #define d, and so the bitmap resource will be identified by the literal name "RC_REDBACK" and not by the ID number 1000 . RC_REDBACKRC_REDBACK将不会是#define d,因此位图资源将由文字名称"RC_REDBACK"而非ID号1000标识。 As such, you will have to use LoadFromResouceName() instead of LoadFromResourceID() : 这样,您将必须使用LoadFromResouceName()而不是LoadFromResourceID()

     RedBack->LoadFromResourceName((unsigned)HInstance, "RC_REDBACK"); 

    Use a resource viewer tool to verify how your resources are actually identified in the final executable. 使用资源查看器工具来验证最终可执行文件中如何实际标识您的资源。

  • inside of CardBackTst() , the global Form1 pointer may not have been assigned yet, since the TForm1 object is still being constructed. CardBackTst()内部,可能尚未分配全局Form1指针,因为仍在构造TForm1对象。 CardBackTst() should not be relying on the global pointer at all. CardBackTst() 不应依赖全局指针。 It should take the Form pointer as an input parameter instead: 它应该使用Form指针作为输入参数:

     //#include "ResRC.h" void CardBackTst(TForm1 *Form) { Graphics::TBitmap* RedBack = new Graphics::TBitmap; if (Form) Form->Debug->Text = DEBUGTEXT; //RedBack->LoadFromResourceID((unsigned)HInstance, RC_REDBACK); RedBack->LoadFromResourceName((unsigned)HInstance, "RC_REDBACK"); } ... __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { CardBackTst(this); } 

    A better solution would be to pass in the TEdit directly instead of the TForm itself: 更好的解决方案是直接传递TEdit而不是TForm本身:

     //#include "ResRC.h" void CardBackTst(TEdit *Debug) { Graphics::TBitmap* RedBack = new Graphics::TBitmap; if (Debug) Debug->Text = DEBUGTEXT; //RedBack->LoadFromResourceID((unsigned)HInstance, RC_REDBACK); RedBack->LoadFromResourceName((unsigned)HInstance, "RC_REDBACK"); } ... __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { CardBackTst(Debug); } 

    Or, use a callback function instead: 或者,改用回调函数:

     //#include "ResRC.h" typedef void __fastcall (__closure *TCardDebugProc)(const String &); void CardBackTst(TCardDebugProc DebugProc) { Graphics::TBitmap* RedBack = new Graphics::TBitmap; if (DebugProc) DebugProc(DEBUGTEXT); //RedBack->LoadFromResourceID((unsigned)HInstance, RC_REDBACK); RedBack->LoadFromResourceName((unsigned)HInstance, "RC_REDBACK"); } ... __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { CardBackTst(&LogDebug); } void __fastcall TForm1::LogDebug(const String &DebugText) { Debug->Text = DebugText; } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM