2014-09-14 2 views
1

Я в ситуации, когда получает от Lua таблицу строк. Мне нужно скопировать строки в массив, чтобы вызвать внутреннюю функцию C. Обработка строк является локальной для объема функции (т. Е. После того, как функция возвращает данные, строки не сохраняются).Нужно дублировать строки таблицы для локальной обработки области?

На данный момент, я что-то вроде этого:

int process_tokens(lua_State *lua) 
{ 
    char *tokens[TOKENS_MAX]; 
    int ntokens = 0; 

    /* assume table at top */ 
    while (ntokens < sizeof(tokens)/sizeof(*tokens)) { 
     lua_rawgeti(lua, -1, ntokens + 1); 
     if (lua_isnil(lua, -1)) 
      break; 
     tokens[ntokens++] = luaL_checkstring(lua, -1); 
     lua_pop(lua, 1); 
    } 

    lua_pushnumber(lua, handle_tokens(tokens, ntokens)); 
    return 1; 
} 

Теперь мой вопрос: является ли он безопасным для не дублировать строки здесь? Я бы склонен думать, что да, так как таблица, содержащая их, не может быть gc'ed до тех пор, пока функция process_tokens() не вернется (если она не выскользнула из стека), поэтому строки, которые она содержит, тоже не могут быть. С другой стороны, я не нашел каких-либо указаний относительно того, где указатель, полученный при вызове luaL_checkstring(), фактически указывает на (внутри объекта? Какой-то временный стек где-нибудь?).

+0

['lua_tolstring возвращает полностью выровненный указатель к строке внутри состояния Lua. '] (http://www.lua.org/manual/5.1/manual.html#lua_tolstring) –

+1

Если вы знаете, что эта таблица не может быть вызвана функцией и что' handle_tokens' не измените строки, которые он задает каким-либо образом (в том числе не желая получать один и тот же указатель для нескольких записей), тогда я считаю, что это безопасно. –

+1

В общем, указатели, полученные от Lua в Lua CFunction, гарантированно остаются в силе во время работы CFunction. – lhf

ответ

1

Я думаю, что вы просите о проблемах, если вы не копируете персонажей. Документы говорят, что для lua_tolstring, «Поскольку у Lua есть сбор мусора, нет гарантии, что указатель, возвращенный lua_tolstring, будет действителен после того, как соответствующее значение будет удалено из стека.« С вашего поста появляется , вероятно,, что char* указывает на память, которая будет действительна в течение всего времени жизни таблицы, но что, если указатель соответствует копии строки, которая была в объекте Lua? Это было бы удивительно, но единственный верный способ узнать - посмотреть на исходный код Lua.

Другая причина, по которой не копирование искала проблемы (значит, сейчас это нормально, но может измениться без предупреждения), заключается в том, что любые изменения в вашем скрипте, которые лишают вас предположения, приведут к повреждению памяти без предупреждения. То есть, даже если ваш код C не получит уведомление, когда память, на которую указывает возвращаемый указатель lua_ltostring, является gc'd (и умные трюки для получения уведомлений, такие как __del metamethod, будут нести их собственный штраф за производительность) ,

Итак, вернемся к основам оптимизации: вы действительно обеспокоены тем, что обсуждаемая строковая копия будет узким местом в вашем приложении? Потому что, если нет, это преждевременная оптимизация, и это может привести к ошибке, которая очень трудоемка изолировать год от времени, когда вы забыли все об этом невинно выглядящем «ярлыке» :)

+0

Что касается функциональной документации, мне не ясно, что она подразумевает на практике. Я просто прочитал еще один абзац: «Стол со слабыми ключами позволяет собирать его ключи», поэтому его достаточно для меня. Я пойду безопасным способом, как вы предлагаете, и используйте более безопасный метод для передачи данных. – michaelmeyer

Смежные вопросы