Обработка строк C++

1112 Прежде всего - совершенно невозможно понять, чего вы хотите. Ваш пост начинается с:

Мы можем установить ...

Мы должны установить ...

Никто здесь не знает, что вы хотите сделать, и было бы гораздо полезнее увидеть какое-то определение того, что вы ожидаете.

Сказав это сейчас, я должен перейти к вашему основному вопросу ...

  env:
    - name: CALLERPORT
      value: "8080"
    - name: CALLEDADDRESS
      value: called-loadbalancer  # WHAT TO PUT HERE?!
    ports:
    - containerPort: 8080
      name: caller

Эти вещи будут автоматически экспортированы k8s. Например, у меня есть служба kibana с port:80 в определении службы:

svc/kibana                                 ClusterIP      10.222.81.249    <none>                              80/TCP              1y        app=kibana

, вот как я могу получить это в другом модуле, который находится в том же пространстве имен:

[112 ]

Двигаясь вперед, почему вы используете LoadBalancer? Без какого-либо облака это будет похоже на NodePort, но, похоже, ClusterIP - это все, что вам нужно. Далее, сервисные порты могут быть одинаковыми, и не будет никаких конфликтов портов, просто потому, что ClusterIP каждый раз уникален и, следовательно, сокет будет уникальным для каждого сервиса. Ваши сервисы можно описать так:

apiVersion: v1
kind: Service              
metadata:
  name: caller-loadbalancer
spec:
  type: LoadBalancer       
  ports:
  - port: 80 <--------------------           
    targetPort: 8080        
  selector:            
    app: caller  

apiVersion: v1
kind: Service              
metadata:
  name: called-loadbalancer
spec:
  type: LoadBalancer       
  ports:
  - port: 80 <------------------             
    targetPort: 8081        
  selector:            
    app: called

Это упростит использование имен сервисов только по именам без указания портов:

http://caller-loadbalancer.default.svc.cluster.local
http://called-loadbalancer.default.svc.cluster.local

или

http://caller-loadbalancer.default
http://called-loadbalancer.default

или (в аналогичном пространстве имен):

http://caller-loadbalancer
http://called-loadbalancer

или (в зависимости от библиотеки)

caller-loadbalancer
called-loadbalancer

То же самое в containerPort / targetPort! Почему вы используете 8081 и 8080? Кто заботится о внутренних портах контейнера? Я согласен, что бывают разные случаи, но в этом случае у вас внутри один процесс, и вы определенно не собираетесь запускать еще несколько процессов, не так ли? Так что они тоже могут быть одинаковыми.

Я хотел бы посоветовать вам использовать стекопоток другим способом. Не спрашивайте, как сделать что-то по-своему, гораздо лучше спросить, как сделать что-то наилучшим образом

6
задан xan 18 July 2011 в 09:32
поделиться

13 ответов

Наблюдение теперь, когда проблема - то, как очистить строку, которую Вы создали и передали LoadAndSetUpData ()

Я предполагаю что:

  1. LoadAndSetUpData () не делает свою собственную копию
  2. Вы не можете изменить LoadAndSetUpData (), чтобы сделать это
  3. Вам нужна строка для тихого существования в течение некоторого времени после LoadAndSetupData () возвраты

Вот предложения:

  1. Можно ли сделать собственные объекты очереди, которые назовут? Их, как гарантируют, назовут после тех, которые используют Вашу строку. Если так, создайте события очереди очистки с той же строкой, которую вызов удаляет [] на них

  2. Есть ли максимальное количество, на которое можно рассчитывать. При создании большого массива строк могли Вы использовать их в цикле, и гарантированы, что, когда Вы возвратились к началу, будет нормально снова использовать ту строку

  3. Существует ли количество времени, на которое можно рассчитывать? Если так, зарегистрируйте их для удаления где-нибудь и проверьте это через какое-то время.

Лучшая вещь была бы для функций, которые берут символ* для взятия владения или копии. Общее владение является самой твердой вещью обойтись без подсчета ссылок или сборки "мусора".

3
ответ дан 8 December 2019 в 16:13
поделиться

Я не полностью ясен на том, где LoadAndSetupData определяется, но похоже, что это сохраняет свою собственную копию строки. Таким образом необходимо удалить локально выделенную копию после вызова к LoadAndSetupData и позволить ему управлять своей собственной копией.

Или, удостоверьтесь, что LoadAndSetupData очищает выделенный символ [], что Вы даете его.

Мое предпочтение состояло бы в том, чтобы позволить другому функциональному содержанию его собственная копия и управлять им так, чтобы Вы не выделяли объект для другого класса.

Править: так как Вы используете новый с фиксированным размером [50], Вы могли бы также сделать его локальным, как был предложен, и LoadAndSetupData, которым позволяют, делают его собственную копию.

-1
ответ дан 8 December 2019 в 16:13
поделиться

Можно объединить некоторые идеи здесь.

В зависимости от того, как Вы построили свое приложение из модулей, может быть метод (основной?), чье выполнение определяет объем, в котором nameToUse определим как локальная переменная фиксированного размера. Можно передать указатель (&nameToUse[0] или просто nameToUse) к тем другим методам, которые должны заполнить его (так передайте размер также), или используйте его, зная, что устройство хранения данных исчезнет, когда функция, имеющая выходы локальной переменной или программу, завершится любыми другими средствами.

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

0
ответ дан 8 December 2019 в 16:13
поделиться

Слова благодарности все для Ваших ответов. Я не выбрал тот как "ответ", поскольку нет конкретного решения этой проблемы, и лучшие обсуждения его являются всем upvoted быть я и другими так или иначе.

Ваши предложения являются всей пользой, и Вы были очень терпеливы с неуклюжим из моего вопроса. Поскольку я уверен, что Вы видите, это - упрощение более сложной проблемы и существует намного больше продолжения, которое соединено с примером, который я дал, следовательно способ, которым биты его не могли полностью иметь смысла.

Для Вашего интереса я решил "обмануть" свой выход из трудности на данный момент. Я сказал, что базовые имена были произвольны, но это не довольно верно. На самом деле они - ограниченный набор имен также, просто ограниченный набор, который мог измениться в какой-то момент, таким образом, я пытался решить более общую проблему.

На данный момент я расширю "статическое" решение суффиксов и создам таблицу возможных имен. Это очень "hacky", но будет работать и кроме того старается не осуществлять рефакторинг большой объем сложного кода, который я не могу.

Обратная связь была фантастической, большое спасибо.

0
ответ дан 8 December 2019 в 16:13
поделиться

Во-первых: Почему Вам нужно, чтобы выделенная строка сохранилась вне конца LoadStuff ()? Есть ли способ, которым можно осуществить рефакторинг для удаления того требования.

Так как C++ не обеспечивает простой способ сделать этот вид материала, большинство сред программирования использует ряд инструкций об указателях для предотвращения, удаляют/освобождают проблемы. Так как вещи могут только быть выделены/освобождены однажды, должно быть очень ясно, кто "владеет" указателем. Некоторые демонстрационные инструкции:

1) Обычно человек, который выделяет строку, является владельцем и также ответственен за освобождение строки.

2) Если необходимо освободить в другой функции/классе, чем Вы выделили в, должна быть явная передача владения к другому классу/функции.

3) Если явно не указано иначе, указатели (включая строки) принадлежат вызывающей стороне. Функция, конструктор, и т.д. не может предположить, что указатель строки, который это получает, сохранится вне конца вызова функции. Если им нужна персистентная копия указателя, они должны сделать локальную копию с strdup ().

То, к чему это сводится в Вашем конкретном случае, - то, что LoadStuff () должен удалить [] nameToUse, и функция, которую он вызывает, должна сделать локальную копию.

Одно альтернативное решение: если nameToUse будет переданным много мест и должен сохраниться в течение времени жизни программы, Вы могли сделать это глобальной переменной. (Это избавляет от необходимости делать много копий его.), Если Вы не хотите загрязнять свое глобальное пространство имен, Вы могли бы просто объявить это статичный локальный для функции:

static char *nameToUse = new char[50];
0
ответ дан 8 December 2019 в 16:13
поделиться

Где точно nameToUse используется вне объема LoadStuff? Если кому-то нужен он после LoadStuff, это должно передать его, наряду с ответственностью за освобождение памяти

Если Вы сделали бы это в c#, как Вы предположили

LoadAndSetupData(mBaseName + GetSuffix()); 

затем ничто не сослалось бы на параметр LoadAndSetupData, поэтому можно безопасно изменить его на

char nameToUse[50];

как предложенный Martin.

0
ответ дан 8 December 2019 в 16:13
поделиться

Если необходимо использовать символьный *, то LoadAndSetupData () должен явно зарегистрировать, кто владеет памятью для символа* после вызова. Можно сделать одну из двух вещей:

  1. Скопируйте строку. Это - вероятно, самая простая вещь. LoadAndSetupData копирует строку в некоторый внутренний буфер, и вызывающая сторона всегда ответственна за память.

  2. Владение передачи. LoadAndSetupData () документы, что это будет ответственно за то, что в конечном счете освободило память для char*. Вызывающая сторона не должна волноваться об освобождении памяти.

Я обычно предпочитаю безопасное копирование как в № 1, потому что средство выделения строки также ответственно за освобождение его. Если Вы идете с № 2, средство выделения должно помнить НЕ к свободным вещам, и управление памятью происходит в двух местах, которые я нахожу тяжелее для поддержания. В любом случае это - вопрос явного документирования политики так, чтобы вызывающая сторона знала, что ожидать.

Если Вы идете с № 1, смотрите на ответ Lou Franco, чтобы видеть, как Вы могли бы выделить символ [] в безопасном от исключения, верном, чтобы быть освобожденным способом использовать защитный класс. Обратите внимание, что Вы не можете (безопасно) использовать станд.:: auto_ptr для массивов.

2
ответ дан 8 December 2019 в 16:13
поделиться

Вы оказываетесь перед необходимостью управлять временем жизни памяти, которую Вы выделяете для nameToUse. Оборачивание его в классе, таком как станд.:: строка делает Вашу жизнь немного более простой.

Я предполагаю, что это - незначительное негодование, но так как я не могу думать ни о каком лучшем решении Вашей проблемы, я укажу на другую потенциальную проблему. Необходимо очень стараться проверить размер буфера, в который Вы вписываете при копировании или конкатенации строк. Функции, такие как strcat, strcpy и sprintf могут легко перезаписать конец своих целевых буферов, ведя к побочным ошибкам периода выполнения и уязвимостям системы обеспечения безопасности.

Извинения, мой собственный опыт находится главным образом на платформе Windows, где они представили "безопасные" версии этих функций, вызванных strcat_s, strcpy_s, и sprintf_s. То же идет для всех их многих связанных функций.

0
ответ дан 8 December 2019 в 16:13
поделиться

Начиная со станд.:: строка не является опцией по любой причине, Вы изучили интеллектуальные указатели? Посмотрите повышение

Но я могу только поощрить Вас использовать станд.:: строка.

Христианин

2
ответ дан 8 December 2019 в 16:13
поделиться

Так как Вам нужен nameToUse для тихого существования после функции, Вы застреваете с помощью нового, что я сделал бы, возвратить указатель на него, таким образом, вызывающая сторона может "удалить" его в более позднее время, когда это больше не необходимо.

char * LoadStuff()
{
    char* suffix = GetSuffix();
    char* nameToUse = new char[50];
    sprintf("%s%s",mBaseName,suffix);

    LoadAndSetupData(nameToUse);
    return nameToUse;
}

затем:

char *name = LoadStuff();
// do whatever you need to do:
delete [] name;
2
ответ дан 8 December 2019 в 16:13
поделиться

Вещью помнить с управлением памятью C++ является владение. Если данные LoadAndSetupData не собираются брать владение строки, то это - все еще Ваша ответственность. Так как Вы не можете сразу удалить его (из-за проблемы asynchronicity), Вы оказываетесь перед необходимостью держаться за те указатели до тех пор, пока Вы знаете, что можно удалить их.

Поддержите пул строк, которые Вы создали:

  • Если у Вас есть некоторый момент времени, где Вы знаете, что с очередью полностью имели дело, можно просто удалить все строки в пуле.
  • Если Вы знаете, что со всеми строками, созданными после определенного момента вовремя, имели дело, то отслеживают то, когда строки были созданы, и можно удалить то подмножество. - Если можно так или иначе узнать, когда с отдельной строкой имели дело, затем просто, удалите ту строку.

class StringPool
{
    struct StringReference {
        char *buffer;
        time_t created;
    } *Pool;

    size_t PoolSize;
    size_t Allocated;

    static const size_t INITIAL_SIZE = 100;

    void GrowBuffer()
    {
        StringReference *newPool = new StringReference[PoolSize * 2];
        for (size_t i = 0; i < Allocated; ++i)
            newPool[i] = Pool[i];
        StringReference *oldPool = Pool;
        Pool = newPool;
        delete[] oldPool;
    }

public:

    StringPool() : Pool(new StringReference[INITIAL_SIZE]), PoolSize(INITIAL_SIZE)
    {
    }

    ~StringPool()
    {
        ClearPool();
        delete[] Pool;
    }

    char *GetBuffer(size_t size)
    {
        if (Allocated == PoolSize)
            GrowBuffer();
        Pool[Allocated].buffer = new char[size];
        Pool[Allocated].buffer = time(NULL);
        ++Allocated;
    }

    void ClearPool()
    {
        for (size_t i = 0; i < Allocated; ++i)
            delete[] Pool[i].buffer;
        Allocated = 0;
    }

    void ClearBefore(time_t knownCleared)
    {
        size_t newAllocated = 0;
        for (size_t i = 0; i < Allocated; ++i)
        {
            if (Pool[i].created < knownCleared)
            {
                delete[] Pool[i].buffer;
            }
            else
            {
                Pool[newAllocated] = Pool[i];
                ++newAllocated;
            }
        }
        Allocated = newAllocated;
    }

    // This compares pointers, not strings!
    void ReleaseBuffer(char *knownCleared)
    {
        size_t newAllocated = 0;
        for (size_t i = 0; i < Allocated; ++i)
        {
            if (Pool[i].buffer == knownCleared)
            {
                delete[] Pool[i].buffer;
            }
            else
            {
                Pool[newAllocated] = Pool[i];
                ++newAllocated;
            }
        }
        Allocated = newAllocated;
    }

};
3
ответ дан 8 December 2019 в 16:13
поделиться

Править: Этот ответ не решает его проблему полностью - я сделал другие предложения здесь: обработка строк C++

Его проблема состоит в том, что он должен расширить объем символа*, он создал к внешней стороне функцию, и пока асинхронное задание не закончено.

Исходный ответ:

В C++, если я не могу пользоваться стандартной библиотекой или Повышением, у меня все еще есть класс как это:

template<class T>
class ArrayGuard {
  public:
    ArrayGuard(T* ptr) { _ptr = ptr; }
    ~ArrayGuard() { delete[] _ptr; }
  private:
    T* _ptr;
    ArrayGuard(const ArrayGuard&);
    ArrayGuard& operator=(const ArrayGuard&);
}

Вы используете его как:

char* buffer = new char[50];
ArrayGuard<char *> bufferGuard(buffer);

Буфер будет удален в конце объема (по возврату или броску).

Для просто удаления простого массива для динамических размерных массивов, что я хочу рассматриваться как статический размерный массив, который выпущен в конце объема.

Сохраните это простым - при необходимости в более необычных интеллектуальных указателях используйте Повышение.

Это полезно, если 50 в Вашем примере являются переменными.

3
ответ дан 8 December 2019 в 16:13
поделиться

Нет никакой потребности выделить на "куче" в этом случае. И всегда используйте snprintf:

char nameToUse[50];
snprintf(nameToUse, sizeof(nameToUse), "%s%s",mBaseName,suffix);
1
ответ дан 8 December 2019 в 16:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: