# [Debugger] Determine a breakpoint line is valid

This topic is 509 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi guys,

I would like to know if a breakpoint set on certain line is valid before it actually being hit.

I'm currently do some debugging implementation. e.g. user set the breakpoints and after launching the script, some of the invalid breakpoints shown as invalid in the GUI (i.e. they are not inside of any functions).

I have studied the official debugger add-on and it has CheckBreakPoint function which checks the breakpoints when the code runs to the line, however, I really want to know if this line is valid or should be moved to some near line BEFORE it gets hit.

Do you have any ideas?

Cheers!

Edited by hobbydev

##### Share on other sites

To do that you can enumerate all the functions and class methods in the module and look for the one that contains the wanted break point and then, just as the CDebugger add-on does, use FindNextLineWithCode to find the valid line for the breakpoint.

##### Share on other sites

Is FindNextLineWithCode of a function still avaible even the code is not running inside this function?

##### Share on other sites

Yes, it can be used even when the VM is not running.

##### Share on other sites

Thank you Andreas! I will have a try! :D

##### Share on other sites

Hi Andreas,

I've tried the approach, and it works well for functions.

However, it's not working for ObjectType methods or global variables.

(e.g. Test::method() or string g_str = getDefaultString(); of script.as from asrun sample)

Thank you very much! :ph34r:

Edited by hobbydev

##### Share on other sites

For global variables there is currently no interface for obtaining the position where the variable has been declared. I'll see if I can add this for the upcoming release (2.32.0). If you don't want to wait until I can provide code changes, you ought to be able to do it yourself with a bit of customization of the library (look for the class asCGlobalProperty and then in the member initFunc (type asCScriptFunction) you'll find the declaredAt and scriptSectionIdx that hold the location where the code was declared)

As for class methods it should be working already. You'll need to enumerate the types to find each of the declared classes, and then for each of the classes you enumerate the methods and factories.

If you're still having trouble, please show me what you've done and the error you're getting so I can investigate it in more detail.

##### Share on other sites

Hi Andreas,

I'm tring the member methods and factories but they failed.

I put my test code into the function body of

void CDebugger::LineCallback(asIScriptContext *ctx)

since I don't know if the running context is dependent.

You can test line 38 of script.as, this is the method() function of class Test. In this test, the FindNextLineWithCode function will always fail due to the condition failure

scriptData == 0

in FindNextLineWithCode function.

Here is my testing code

    int currentLine = ctx->GetLineNumber(0, 0, &file);
if (currentLine == 38)
{
int i = 0; // put a breakpoint here test, line 38 is "void Test::method()"
}

std::cout << "current line: " << currentLine << std::endl;

asIScriptModule* module = engine_->GetModule("script");
if (!module)
return;

// all functions from the object types
std::vector<asIScriptFunction*> allFunctions;

// for each object type
for (size_t i = 0, objectTypeCount = module->GetObjectTypeCount(); i < objectTypeCount; ++i)
{
asITypeInfo* objectType = module->GetObjectTypeByIndex(i);
assert(objectType);
if (!objectType)
continue;

// member methods
for (size_t j = 0, methodCount = objectType->GetMethodCount(); j < methodCount; ++j)
{
asIScriptFunction* func = objectType->GetMethodByIndex(j);
assert(func);
if (func)
{
std::cout << objectType->GetName() << "::" << func->GetName() << std::endl;
allFunctions.push_back(func);
}
}

// factories
for (size_t j = 0, factoryCount = objectType->GetFactoryCount(); j < factoryCount; ++j)
{
asIScriptFunction* func = objectType->GetFactoryByIndex(j);
if (func)
{
std::cout << objectType->GetName() << "::" << func->GetName() << std::endl;
allFunctions.push_back(func);
}
}
}

// check every functions
for (size_t i = 0; i < allFunctions.size(); ++i)
{
asIScriptFunction* func = allFunctions[i];
assert(func);

std::cout << func->GetName();

static int lineNum = 38;
int actualLine = func->FindNextLineWithCode(lineNum);

std::cout << ", line=" << actualLine << std::endl;  // *** in my test, actualLine is always -1 ***
}

Cheers!

Edited by hobbydev

##### Share on other sites
For global variables there is currently no interface for obtaining the position where the variable has been declared. I'll see if I can add this for the upcoming release (2.32.0). If you don't want to wait until I can provide code changes, you ought to be able to do it yourself with a bit of customization of the library (look for the class asCGlobalProperty and then in the member initFunc (type asCScriptFunction) you'll find the declaredAt and scriptSectionIdx that hold the location where the code was declared)

I had a quick test for the way you suggested, it works!

Please have a look at class methods and factories and my testing code as my previous reply.

As for class methods it should be working already. You'll need to enumerate the types to find each of the declared classes, and then for each of the classes you enumerate the methods and factories.

Thank you very much!

Edited by hobbydev

##### Share on other sites

For GetMethodByIndex you need to tell angelscript that you want the non-virtual function so you get the actual implementation: "GetMethodByIndex(j, false)"

The factory will be a bit trickier, just as for global variables there is currently no interface available to do what you want. The function that you get with GetFactory is a stub function that allocate the memory for the object and then internally calls the real constructor that performs the actual initialization. You need to get to the actual constructor so you can check the valid lines for breakpoints.

I can think of two possible ways at the moment:

1. find the matching constructor in the asCObjectType::beh::constructors array. The index for the constructor in the array will be the same index where the factory is stored in asCObjectType::beh::factories array.

2. use the JIT interface to enumerate the bytecode for the factory until you find the asBC_ALLOC instruction that will hold the function id of the constructor.

1. 1
Rutin
19
2. 2
3. 3
JoeJ
15
4. 4
5. 5

• 22
• 19
• 11
• 13
• 17
• ### Forum Statistics

• Total Topics
631697
• Total Posts
3001766
×