• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Gdb Crash - Otx

tiag0_bn

Well-Known Member
Joined
Dec 8, 2011
Messages
181
Reaction score
50
Can someone help me find out the problem that is helping this?

Lua:
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000563a6ca52fa0 in Item::canDecay (this=0x7fc213ccac00) at item.cpp:1695
1695            if(isRemoved())
[Current thread is 1 (Thread 0x7fc21eec5700 (LWP 19286))]
(gdb) bt full
#0  0x0000563a6ca52fa0 in Item::canDecay (this=0x7fc213ccac00) at item.cpp:1695
        it = warning: can't find linker symbol for virtual table for `ItemType' value
warning:   found `Game::playerChangeOutfit(unsigned int, Outfit_t)' instead
@0x7fc1a0132af0: warning: can't find linker symbol for virtual table for `ItemType' value
warning:   found `Game::playerChangeOutfit(unsigned int, Outfit_t)' instead
{
          _vptr.ItemType = 0x563a6c9c3cc8 <Game::playerSay(unsigned int, unsigned short, MessageClasses, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, loaded = false, stopTime = false,
          showCount = false, stackable = false, showDuration = false, showCharges = false, showAttributes = false, dualWield = false, allowDistRead = 192,
          canReadText = 88, canWriteText = 242, forceSerialize = 108, isVertical = 58, isHorizontal = 86, isHangable = false, usable = false, movable = 136,
          pickupable = 154, rotable = false, replacable = 16, lookThrough = false, walkStack = false, hasHeight = false, blockSolid = false, blockPickupable = true,
          blockProjectile = false, blockPathFind = false, allowPickupable = false, alwaysOnTop = 193, floorChange = {127, false, false, 40, 43, 19, 160, 193, 127},
          isAnimation = false, specialDoor = false, closingDoor = false, cache = false, magicEffect = MAGIC_EFFECT_DRAW_BLOOD, fluidSource = 2686318848,
          weaponType = 32705, bedPartnerDir = 2684744112, ammoAction = 32705, combatType = 2685610824, corpseType = 32705, shootType = SHOOT_EFFECT_SMALLSTONE,
          ammoType = AMMO_NONE, transformBed = {30821, 30309}, transformUseTo = 8303, transformEquipTo = 28515, transformDeEquipTo = 110, id = 26998, clientId = 115,
          maxItems = 0, slotPosition = 181, wieldPosition = 0, speed = 0, maxTextLength = 0, writeOnceItemId = 0, wareId = 0, premiumDays = 0, attack = 1821798976,
          extraAttack = 22074, defense = 0, extraDefense = 32705, armor = 0, breakChance = 32705, hitChance = 603132160, maxHitChance = 32706, runeLevel = 1821725410,
          runeMagLevel = 22074, lightLevel = -1610609808, lightColor = 32705, decayTo = -1610584928, rotateTo = 32705, alwaysOnTopOrder = -1610472032,
          extraAttackChance = 32705, extraDefenseChance = 2, attackSpeedChance = 0, armorRndMin = 0, armorRndMax = 0, defenseRndMin = -1610042944,
          defenseRndMax = 32705, extraDefenseRndMin = -1610472044, extraDefenseRndMax = 32705, attackRndMin = 2, attackRndMax = 0, extraAttackRndMin = 1,
          extraAttackRndMax = 32705, attackSpeedRndMin = 0, attackSpeedRndMax = 0, shootRange = 1821719640, charges = 22074, decayTime = 0, attackSpeed = 0,
          wieldInfo = 0, minReqLevel = 0, minReqMagicLevel = 0, worth = 0, levelDoor = 160, date = 0, name = <error: Cannot access memory at address 0x35>,
          pluralName = "P\263\203\030\302\177\000\000\005\000\000\v", '\000' <repeats 20 times>, "\220\350\204\030\302\177\000\000\270\350\204\030\302\177\000\000P\263\203\030\302\177\000\000\000\000\000\000rer\000P\000\000\000\000\000\000\000E\000\000\000\000\000\000\000\001\000\000\000\302\177\000\000\060\375V\361\301\177\000\000\260\221\333\030\302\177\000\000`]\274\030\302\177\000\000p\000\000\000\000\000\360?\240\260\330\030\302\177\000\000\201\300\006\000\301\300\006\000\065", '\000' <repeats 15 times>, "\004\002\000\030ΐږ\016\000\000\000\000\000\000\000isPlayerSaving\000\000%", '\000' <repeats 15 times>...,
          article = <error: Cannot access memory at address 0x10106>, description = <error: Cannot access memory at address 0x35>,
          text = "\220\204|\361\301\177\000\000\005\004\000\f", '\000' <repeats 20 times>, "\320a\364\030\302\177\000\000\360v\366\030\302\177", '\000' <repeats 14 times>, "LUES \000\\0\000\000\060\000e\000\000\000\000\000\000\000@\243\210\316\301\177\000\000\005\002\377\000\301\177", '\000' <repeats 18 times>, "`\244n$\302\177\000\000`\244n$\302\177\000\000 \242\204\360\301\177\000\000\000\000\000\000\301\177\000\000\004\000\000\000:V\000\000\000\000\000\000\000\000\000\000`\000\000\000\000\000\000\000%\000\000\000\000\000\000\000\220\\\245\314\301\177\000\000\220\\\245\314\301\177\000\000\000\000\000\000\000\000\000\000"...,
          writer = <error reading variable: Cannot create a lazy string with address 0x0, and a non-zero length.>,
          runeSpellName = "\b\347\246l:V\000\000\201\000\000\000\000\000\000\000\260,\023\240\301\177\000\000\360\000\000\240\301\177\000\000Zs\020#\302\177", '\000' <repeats 19 times>, "\205\r\240\301\177", '\000' <repeats 18 times>, "\260\361\005\240\301\177\000\000\000\000\000\000\000\000\000\000@\000\033\240\301\177", '\000' <repeats 26 times>, "\200\000\000\000\000\000\000\000\224\000\000\000\000\000\000\000\240v\233\030\302\177\000\000\004\001\000\000\263\235}\346o\000\000\000\000\000\000\000Dioutromundo [73], Rlue Bune [32"..., vocationString = "", condition = 0x0, abilities = 0x7fc1a01e09a0, group = ITEM_GROUP_NONE, type = ITEM_TYPE_NONE, weight = 0}
#1  0x0000563a6c9c8c40 in Game::startDecay (this=0x563a6cf258c0 <g_game>, item=0x7fc213ccac00) at game.cpp:4872
No locals.
#2  0x0000563a6cbb85df in ConjureSpell::internalConjureItem (player=0x7fc1f2643bf0, conjureId=2544, conjureCount=20, transform=false, reagentId=0) at spells.cpp:1636
        newItem = 0x7fc213ccac00
        ret = RET_TILEISFULL
        containers = std::__cxx11::list = {[0] = 0x6, [1] = 0x563a6cf1a418 <vtable for Door+24>,
          [2] = 0x1089480824448b48<error reading variable: Cannot access memory at address 0x247c894818ec8348>...}
        item = 0x563a6c937b7f <Tile::getZone() const+85>
        fromItem = 0x7fc21eec48d4
#3  0x0000563a6cbb8bb0 in ConjureSpell::ConjureItem (spell=0x7fc21342ff70, creature=0x7fc1f2643bf0) at spells.cpp:1716
        player = 0x7fc1f2643bf0
---Type <return> to continue, or q <return> to quit---
        result = RET_NOTPOSSIBLE
#4  0x0000563a6cbb8dc4 in ConjureSpell::castInstant (this=0x7fc21342ff70, player=0x7fc1f2643bf0, param="") at spells.cpp:1734
        var = {type = 9, text = "", pos = {<Position> = {x = 18842, y = 7916, z = 32706}, stackpos = 0}, number = 268475016}
#5  0x0000563a6cbafb21 in Spells::onPlayerSay (this=0x7fc218267bd0, player=0x7fc1f2643bf0, words="exevo con") at spells.cpp:74
        reWords = "exevo con"
        instantSpell = 0x7fc21342ff70
        size = 9
        param = ""
        reParam = ""
        pos = {x = 33201, y = 32412, z = 6}
        type = 32706
        ret = ""
#6  0x0000563a6c9c3f61 in Game::playerSay (this=0x563a6cf258c0 <g_game>, playerId=268475016, channelId=0, type=MSG_SPEAK_SAY, receiver="", text="exevo con")
    at game.cpp:3923
        player = 0x7fc1f2643bf0
        muted = 0
        mute = true
        ret = RET_NOERROR
        statementId = 0
#7  0x0000563a6cb7e7a3 in boost::_mfi::mf5<bool, Game, unsigned int, unsigned short, MessageClasses, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::operator() (this=0x7fc1a0132af0,
    p=0x563a6cf258c0 <g_game>, a1=268475016, a2=0, a3=MSG_SPEAK_SAY, a4="", a5="exevo con") at /usr/include/boost/bind/mem_fn_template.hpp:619
No locals.
#8  0x0000563a6cb7c8e5 in boost::_bi::list6<boost::_bi::value<Game*>, boost::_bi::value<unsigned int>, boost::_bi::value<unsigned short>, boost::_bi::value<MessageClasses>, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::operator()<bool, boost::_mfi::mf5<bool, Game, unsigned int, unsigned short, MessageClasses, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>, boost::_bi::list0> (
    this=0x7fc1a0132b00, f=..., a=...) at /usr/include/boost/bind/bind.hpp:592
No locals.
#9  0x0000563a6cb792cc in boost::_bi::bind_t<bool, boost::_mfi::mf5<bool, Game, unsigned int, unsigned short, MessageClasses, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>, boost::_bi::list6<boost::_bi::value<Game*>, boost::_bi::value<unsigned int>, boost::_bi::value<unsigned short>, boost::_bi::value<MessageClasses>, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::operator() (
    this=0x7fc1a0132af0) at /usr/include/boost/bind/bind.hpp:1294
        a = {<No data fields>}
#10 0x0000563a6cb75fe0 in boost::detail::function::void_function_obj_invoker0<boost::_bi::bind_t<bool, boost::_mfi::mf5<bool, Game, unsigned int, unsigned short, MessageClasses, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>, boost::_bi::list6<boost::_bi::value<Game*>, boost::_bi::value<unsigned int>, boost::_bi::value<unsigned short>, boost::_bi::value<MessageClasses>, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, void>::invoke (function_obj_ptr=...) at /usr/include/boost/function/function_template.hpp:159
        f = 0x7fc1a0132af0
#11 0x0000563a6c9a9494 in boost::function0<void>::operator() (this=0x7fc1f258f880) at /usr/include/boost/function/function_template.hpp:759
No locals.
---Type <return> to continue, or q <return> to quit---
#12 0x0000563a6c9a8b06 in Task::operator() (this=0x7fc1f258f870) at dispatcher.h:34
No locals.
#13 0x0000563a6c9a77c1 in Dispatcher::dispatcherThread (this=0x563a6cf22560 <Dispatcher::getInstance()::dispatcher>) at dispatcher.cpp:71
        task = 0x7fc1f258f870
        outputPool = 0x563a6cf224a0 <OutputMessagePool::getInstance()::instance>
        taskLockUnique = {m = 0x563a6cf22578 <Dispatcher::getInstance()::dispatcher+24>, is_locked = false}
#14 0x0000563a6c9abfe2 in boost::_mfi::mf0<void, Dispatcher>::operator() (this=0x563a6dd95cd8, p=0x563a6cf22560 <Dispatcher::getInstance()::dispatcher>)
    at /usr/include/boost/bind/mem_fn_template.hpp:49
No locals.
#15 0x0000563a6c9abf46 in boost::_bi::list1<boost::_bi::value<Dispatcher*> >::operator()<boost::_mfi::mf0<void, Dispatcher>, boost::_bi::list0> (this=0x563a6dd95ce8,
    f=..., a=...) at /usr/include/boost/bind/bind.hpp:259
No locals.
#16 0x0000563a6c9abd62 in boost::_bi::bind_t<void, boost::_mfi::mf0<void, Dispatcher>, boost::_bi::list1<boost::_bi::value<Dispatcher*> > >::operator() (
    this=0x563a6dd95cd8) at /usr/include/boost/bind/bind.hpp:1294
        a = {<No data fields>}
#17 0x0000563a6c9abb04 in boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, Dispatcher>, boost::_bi::list1<boost::_bi::value<Dispatcher*> > > >::run (this=0x563a6dd95b20) at /usr/include/boost/thread/detail/thread.hpp:116
No locals.
#18 0x00007fc223811bcd in ?? () from /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.65.1
No symbol table info available.
#19 0x00007fc2235e86db in start_thread (arg=0x7fc21eec5700) at pthread_create.c:463
        pd = 0x7fc21eec5700
        now = <optimized out>
        unwind_buf = {cancel_jmp_buf = {{jmp_buf = {140471719188224, -7303291020785063027, 140471719186368, 0, 94808951053088, 140723178739440, 7287178627598150541,
                7287168618491177869}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
        not_first_call = <optimized out>
#20 0x00007fc22239071f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
 
Solution
OTX 2 coding style:
C++:
        ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true);
        if(ret != RET_NOERROR)
            delete newItem;

        g_game.startDecay(newItem);
        return ret;
delete item and call function on it :)

FIX:
C++:
        ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true);
        if(ret != RET_NOERROR) {
            delete newItem;
        } else {
            g_game.startDecay(newItem);
        }

        return ret;

EDIT:
It's even fixed in current OTX2:
To interpret the GDB back trace, you should follow the #'s in reverse order.

From #20 to #7 there is nothing worthy.

#6 is saying that something happend when a player say "exevo con":
#6 0x0000563a6c9c3f61 in Game:: playerSay (this=0x563a6cf258c0 <g_game>, playerId=268475016, channelId=0, type=MSG_SPEAK_SAY, receiver="", text="exevo con")
at game.cpp:3923

#5 is same as #6 (Game:: playerSay was interpreted that the say words was a spell, so it goes to Spells:: onPlayerSay)
#4 is same as #5 (the spell is a conjure spell)
#3 is same as #4 (the conjure spell is conjuring an item)
#2 is same as #3, and here is the error:

#2 0x0000563a6cbb85df in ConjureSpell::internalConjureItem (player=0x7fc1f2643bf0, conjureId=2544, conjureCount=20, transform=false, reagentId=0) at spells.cpp:1636
newItem = 0x7fc213ccac00
ret = RET_TILEISFULL

The tile is full and the server cannot handle it properly.

I don't know how old is your server distribution but I think it is time to you check the code from more stable distributions as TFS and check the differences on its implementation.
 
Im with this problem too

C++:
#0  0x0000000000000045 in ?? ()
#1  0x000056169d782d12 in Item::canDecay (this=0x7f38ca2a4df0) at item.cpp:1691
#2  0x000056169d6fd9ec in Game::startDecay (this=0x56169dc3c700 <g_game>, item=0x7f38ca2a4df0) at game.cpp:4863
#3  0x000056169d8d78b9 in ConjureSpell::internalConjureItem (player=0x7f38db39e790, conjureId=2544, conjureCount=20, transform=false, reagentId=0) at spells.cpp:1635
#4  0x000056169d8d7e8c in ConjureSpell::ConjureItem (spell=0x7f38e098e390, creature=0x7f38db39e790) at spells.cpp:1715
#5  0x000056169d8d80a0 in ConjureSpell::castInstant (this=0x7f38e098e390, player=0x7f38db39e790, param="") at spells.cpp:1733
#6  0x000056169d8cec5f in Spells::onPlayerSay (this=0x7f38e032fa00, player=0x7f38db39e790, words="exevo con") at spells.cpp:74
#7  0x000056169d6f8ced in Game::playerSay (this=0x56169dc3c700 <g_game>, playerId=268452902, channelId=0, type=MSG_SPEAK_SAY, receiver="", text="exevo con") at game.cpp:3914
#8  0x000056169d8a5c90 in boost::_mfi::mf5<bool, Game, unsigned int, unsigned short, MessageClasses, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::operator() (this=0x7f38ac08ae40, p=0x56169dc3c700 <g_game>, a1=268452902, a2=0, a3=MSG_SPEAK_SAY, a4="", a5="exevo con") at /usr/include/boost/bind/mem_fn_template.hpp:619
#9  0x000056169d8a3d61 in boost::_bi::list6<boost::_bi::value<Game*>, boost::_bi::value<unsigned int>, boost::_bi::value<unsigned short>, boost::_bi::value<MessageClasses>, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::operator()<bool, boost::_mfi::mf5<bool, Game, unsigned int, unsigned short, MessageClasses, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>, boost::_bi::list0> (this=0x7f38ac08ae50, f=..., a=...)
    at /usr/include/boost/bind/bind.hpp:592
#10 0x000056169d8a08f2 in boost::_bi::bind_t<bool, boost::_mfi::mf5<bool, Game, unsigned int, unsigned short, MessageClasses, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>, boost::_bi::list6<boost::_bi::value<Game*>, boost::_bi::value<unsigned int>, boost::_bi::value<unsigned short>, boost::_bi::value<MessageClasses>, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::operator() (this=0x7f38ac08ae40)
    at /usr/include/boost/bind/bind.hpp:1294
#11 0x000056169d89e0d3 in boost::detail::function::void_function_obj_invoker0<boost::_bi::bind_t<bool, boost::_mfi::mf5<bool, Game, unsigned int, unsigned short, MessageClasses, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>, boost::_bi::list6<boost::_bi::value<Game*>, boost::_bi::value<unsigned int>, boost::_bi::value<unsigned short>, boost::_bi::value<MessageClasses>, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, boost::_bi::value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, void>::invoke (function_obj_ptr=...) at /usr/include/boost/function/function_template.hpp:159
#12 0x000056169d6de2b6 in boost::function0<void>::operator() (this=0x7f38ac060230) at /usr/include/boost/function/function_template.hpp:759
#13 0x000056169d6dd928 in Task::operator() (this=0x7f38ac060220) at dispatcher.h:34
#14 0x000056169d6dc5e3 in Dispatcher::dispatcherThread (this=0x56169dc39320 <Dispatcher::getInstance()::dispatcher>) at dispatcher.cpp:71
#15 0x000056169d6e0e05 in boost::_mfi::mf0<void, Dispatcher>::operator() (this=0x56169e1accd8, p=0x56169dc39320 <Dispatcher::getInstance()::dispatcher>) at /usr/include/boost/bind/mem_fn_template.hpp:49
#16 0x000056169d6e0d68 in boost::_bi::list1<boost::_bi::value<Dispatcher*> >::operator()<boost::_mfi::mf0<void, Dispatcher>, boost::_bi::list0> (this=0x56169e1acce8, f=..., a=...) at /usr/include/boost/bind/bind.hpp:259
#17 0x000056169d6e0b84 in boost::_bi::bind_t<void, boost::_mfi::mf0<void, Dispatcher>, boost::_bi::list1<boost::_bi::value<Dispatcher*> > >::operator() (this=0x56169e1accd8) at /usr/include/boost/bind/bind.hpp:1294
#18 0x000056169d6e0926 in boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, Dispatcher>, boost::_bi::list1<boost::_bi::value<Dispatcher*> > > >::run (this=0x56169e1acb20)
    at /usr/include/boost/thread/detail/thread.hpp:116
#19 0x00007f38e927dbcd in ?? () from /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.65.1
#20 0x00007f38e90546db in start_thread (arg=0x7f38e4931700) at pthread_create.c:463
#21 0x00007f38e7dfc71f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
 
Im with this problem too

C++:
#3  0x000056169d8d78b9 in ConjureSpell::internalConjureItem (player=0x7f38db39e790, conjureId=2544, conjureCount=20, transform=false, reagentId=0) at spells.cpp:1635
#4  0x000056169d8d7e8c in ConjureSpell::ConjureItem (spell=0x7f38e098e390, creature=0x7f38db39e790) at spells.cpp:1715
#5  0x000056169d8d80a0 in ConjureSpell::castInstant (this=0x7f38e098e390, player=0x7f38db39e790, param="") at spells.cpp:1733
#6  0x000056169d8cec5f in Spells::onPlayerSay (this=0x7f38e032fa00, player=0x7f38db39e790, words="exevo con") at spells.cpp:74
#7  0x000056169d6f8ced in Game::playerSay (this=0x56169dc3c700 <g_game>, playerId=268452902, channelId=0, type=MSG_SPEAK_SAY, receiver="", text="exevo con") at game.cpp:3914

Your stack back trace is almost the same as tiag0_bn, but his is much more detailed. You both should look at ConjureSpell::internalConjureItem.

Do you have the code of this method to post here?
 
Your stack back trace is almost the same as tiag0_bn, but his is much more detailed. You both should look at ConjureSpell::internalConjureItem.

Do you have the code of this method to post here?
Yeah, ofc.

C++:
ReturnValue ConjureSpell::internalConjureItem(Player* player, uint32_t conjureId, uint32_t conjureCount,
    bool transform/* = false*/, uint32_t reagentId/* = 0*/)
{
    if(!transform)
    {
        Item* newItem = Item::CreateItem(conjureId, conjureCount);
        if(!newItem)
            return RET_NOTPOSSIBLE;

        ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true);
        if(ret != RET_NOERROR)
            delete newItem;

        g_game.startDecay(newItem);
        return ret;
    }

    if(!reagentId)
        return RET_NOTPOSSIBLE;

    std::list<Container*> containers;
    Item *item = NULL, *fromItem = NULL;
    for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i)
    {
        if(!(item = player->getInventoryItem((slots_t)i)))
            continue;

        if(!fromItem && item->getID() == reagentId)
            fromItem = item;
        else if(Container* container = item->getContainer())
            containers.push_back(container);
    }

    if(!fromItem)
    {
        for(std::list<Container*>::iterator cit = containers.begin(); cit != containers.end(); ++cit)
        {
            for(ItemList::const_reverse_iterator it = (*cit)->getReversedItems(); it != (*cit)->getReversedEnd(); ++it)
            {
                if((*it)->getID() == reagentId)
                {
                    fromItem = (*it);
                    break;
                }

                if(Container* tmp = (*it)->getContainer())
                    containers.push_back(tmp);
            }
        }
    }

    if(!fromItem)
        return RET_YOUNEEDAMAGICITEMTOCASTSPELL;

    if((fromItem->isStackable() || fromItem->hasCharges()) && fromItem->getSubType() > 1)
    {
        item = Item::CreateItem(conjureId, conjureCount);
        ReturnValue ret = g_game.internalPlayerAddItem(NULL, player, item, false);
        if(ret != RET_NOERROR)
            return ret;

        g_game.transformItem(fromItem, reagentId, (int32_t)(fromItem->getItemCount() - 1));
    }
    else
        g_game.transformItem(fromItem, conjureId, conjureCount);

    g_game.startDecay(item);
    return RET_NOERROR;
}

bool ConjureSpell::ConjureItem(const ConjureSpell* spell, Creature* creature, const std::string&)
{
    Player* player = creature->getPlayer();
    if(!player)
        return false;

    if(!player->hasFlag(PlayerFlag_IgnoreSpellCheck) && player->getZone() == ZONE_HARDCORE)
    {
        player->sendCancelMessage(RET_CANNOTCONJUREITEMHERE);
        g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
        return false;
    }

    ReturnValue result = RET_NOTPOSSIBLE;
    if(spell->getReagentId() != 0)
    {
        if((result = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(), true, spell->getReagentId())) == RET_NOERROR)
        {
            spell->postSpell(player);
            g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED);
            return true;
        }
    }
    else if((result = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount())) == RET_NOERROR)
    {
        spell->postSpell(player);
        g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_WRAPS_RED);
        return true;
    }

    player->sendCancelMessage(result);
    g_game.addMagicEffect(player->getPosition(), MAGIC_EFFECT_POFF);
    return false;
}

bool ConjureSpell::castInstant(Player* player, const std::string& param)
{
    if(!checkSpell(player))
        return false;

    if(!isScripted())
        return function ? function(this, player, param) : false;

    LuaVariant var;
    var.type = VARIANT_STRING;
    var.text = param;
    return executeCastSpell(player, var);
}

RuneSpell::RuneSpell(LuaInterface* _interface):
Action(_interface)
{
    runeId = 0;
    function = NULL;
    hasCharges = allowFarUse = true;
}
 
OTX 2 coding style:
C++:
        ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true);
        if(ret != RET_NOERROR)
            delete newItem;

        g_game.startDecay(newItem);
        return ret;
delete item and call function on it :)

FIX:
C++:
        ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true);
        if(ret != RET_NOERROR) {
            delete newItem;
        } else {
            g_game.startDecay(newItem);
        }

        return ret;

EDIT:
It's even fixed in current OTX2:
 
Last edited:
Solution
Yeah, ofc.

C++:
ReturnValue ConjureSpell::internalConjureItem(Player* player, uint32_t conjureId, uint32_t conjureCount,
    bool transform/* = false*/, uint32_t reagentId/* = 0*/)
{
    if(!transform)
    {
        Item* newItem = Item::CreateItem(conjureId, conjureCount);
        if(!newItem)
            return RET_NOTPOSSIBLE;

        ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true);
        if(ret != RET_NOERROR)
            delete newItem;

        g_game.startDecay(newItem);
        return ret;
    }

    if(!reagentId)
        return RET_NOTPOSSIBLE;

    std::list<Container*> containers;
    Item *item = NULL, *fromItem = NULL;
    for(int32_t i = SLOT_FIRST; i < SLOT_LAST; ++i)
    {
        if(!(item = player->getInventoryItem((slots_t)i)))
            continue;

        if(!fromItem && item->getID() == reagentId)
            fromItem = item;
        else if(Container* container = item->getContainer())
            containers.push_back(container);
    }

    if(!fromItem)
    {
        for(std::list<Container*>::iterator cit = containers.begin(); cit != containers.end(); ++cit)
        {
            for(ItemList::const_reverse_iterator it = (*cit)->getReversedItems(); it != (*cit)->getReversedEnd(); ++it)
            {
                if((*it)->getID() == reagentId)
                {
                    fromItem = (*it);
                    break;
                }

                if(Container* tmp = (*it)->getContainer())
                    containers.push_back(tmp);
            }
        }
    }

    if(!fromItem)
        return RET_YOUNEEDAMAGICITEMTOCASTSPELL;

    if((fromItem->isStackable() || fromItem->hasCharges()) && fromItem->getSubType() > 1)
    {
        item = Item::CreateItem(conjureId, conjureCount);
        ReturnValue ret = g_game.internalPlayerAddItem(NULL, player, item, false);
        if(ret != RET_NOERROR)
            return ret;

        g_game.transformItem(fromItem, reagentId, (int32_t)(fromItem->getItemCount() - 1));
    }
    else
        g_game.transformItem(fromItem, conjureId, conjureCount);

    g_game.startDecay(item);
    return RET_NOERROR;
}
}

The problem is on the very beggining of the ConjureSpell::internalConjureItem.

Replace the:
C++:
    if(!transform)
    {
        Item* newItem = Item::CreateItem(conjureId, conjureCount);
        if(!newItem)
            return RET_NOTPOSSIBLE;
        
        ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true);

        if(ret != RET_NOERROR)
            delete newItem;

        g_game.startDecay(newItem);
        return ret;

    }

To:

C++:
    if(!transform)
    {
        Item* newItem = Item::CreateItem(conjureId, conjureCount);
        if(!newItem)
            return RET_NOTPOSSIBLE;

        ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true);
        if(ret != RET_NOERROR){
            delete newItem;
        }else{
            g_game.startDecay(newItem);
        }
            
        return ret;
    }

The problem is that after deleting a pointer (delete newItem) you are calling g_game.startDecay(newItem) with this null pointer.

You should check if there is no more calls to g_game.startDecay() with a null pointer

Dont know the source code, but maybe you can put something like this on startDecay:

C++:
startDecay(Item* item){
    if(item == nulllptr)
        return;
}

This way it wont crash your code for calling null pointers :)
 
Dont know the source code, but maybe you can put something like this on startDecay:

C++:
startDecay(Item* item){
    if(item == nulllptr)
        return;
}

This way it wont crash your code for calling null pointers :)
Deleting pointer does not set it to null. It still points to RAM address that is deleted:
 
OTX 2 coding style:
C++:
        ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true);
        if(ret != RET_NOERROR)
            delete newItem;

        g_game.startDecay(newItem);
        return ret;
delete item and call function on it :)

FIX:
C++:
        ReturnValue ret = g_game.internalPlayerAddItem(player, player, newItem, true);
        if(ret != RET_NOERROR) {
            delete newItem;
        } else {
            g_game.startDecay(newItem);
        }

        return ret;
Solved Gesior, thanks!
 
Back
Top