Вы можете сделать следующее, чтобы удалить оскорбительный символ, если он присутствует. В противном случае он ничего не будет делать:
your_string.sub(/\*$/, '')
Если вы хотите удалить более одного вхождения символа, вы можете сделать:
your_string.sub(/\*+$/, '')
Конечно, если вы хотите изменить строка на месте, используйте sub! вместо под
Приветствия, Аарон
Потому что то, что на самом деле выглядит после того, как компилятор добился своего, выглядит примерно так:
object::check( object* this )
{
// do stuff without using this
}
int main()
{
object *p = new object;
object::check( p );
delete p;
object::check( p );
delete p;
object::check( p );
}
Поскольку вы не касаетесь «этого», вы фактически не получаете доступа к плохим память.
Хотя двойное удаление p может привести к сбою:
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.2
1) Зависит от компилятора, в Mac OS с gcc 4.0.1:
g++ -Wall -g -c main.cpp -o main.o
g++ -o x main.o
./x
I am doing ok ...
I am doing ok ...
x(5857) malloc: *** error for object 0x100150: double free
*** set a breakpoint in malloc_error_break to debug
I am doing ok ...
Двойное освобождение вызывает проблемы.
2) Обычно удаление указателя, который уже был удален, не определено , вы всегда должны устанавливать указатель на 0 после удаления, вызов delete для указателя со значением 0.
3) Причина, по которой он все еще может печатать строку, заключается в том, что указатель все еще указывает на память, которая теперь была освобождена, но я бы Предположим, что восстанавливается только указатель, например, возвращается в свободный пул для повторного использования, память не перезаписывается и не обнуляется, поэтому при разыменовании указателя вы все равно получите исходные значения, если за это время память не будет повторно использована.
delete не устанавливает p равным нулю, поэтому он по-прежнему указывает на ячейку памяти. Это зависит от реализации new / delete, но обычно при удалении помечается только эта часть памяти как доступная для любых новых выделений.
Это похоже на удаление файла с жесткого диска. Файловая система просто отмечает эту область как доступную. Данные файла существуют и могут быть восстановлены до тех пор, пока вы не будете выполнять новые записи.
Поскольку функция ничего не делает с данными члена объекта или указателем this
.
Это похоже на вызов функции
void check(object *self)
{
std::cout<<"I am doing ok..."<<std::endl;
}
с недопустимым указателем в качестве self
аргумент.
Однако есть двойное удаление, которое может привести к сбою в некоторых средах.
Удаление только освобождает память и делает ее доступной обратно в кучу.
Значение указателя не определено после вызова удаления, поэтому может произойти сбой, а может и не быть.
Совет по программированию, который я использую для уменьшения количества ошибок программирования, заключается в том, чтобы после удаления установить указатель на NULL. Таким образом, вы знаете, что не случайно используете указатель после его удаления.
Вы можете сделать то же самое с указателями nil, если вы никогда не получите доступ к состоянию экземпляра класса:
class object
{
public:
void check()
{
std::cout<<"I am doing ok..."<<std::endl;
}
};
int main()
{
object *p = 0;
p->check();
}
Это еще смешнее. Это прекрасно компилируется и работает:
#include <iostream>
using namespace std;
class object {
public:
void check() {
cout << "I am doing ok..." << endl;
}
};
int main() {
object *p = (object*)0;
p->check();
return 0;
}
В оболочке:
$ g++ -o t t.cc $ ./t I am doing ok... $
:) Вам действительно не нужно иметь объект для вызова этого метода! ура, ч
Даже если при вызове метода использовался указатель this, сбой не гарантировался. Указатель p при удалении не обнуляется, поэтому по-прежнему указывает на тот же адрес в памяти. В зависимости от реализации new / delete и диспетчера кучи, эта память может даже не использоваться повторно, поэтому использование p может продолжать работать, даже если память была освобождена.
Чтобы немного дополнить сказанное другими, попробуйте использовать переменную-член вашего класса внутри метода check (), а затем посмотрите, что произойдет.
Вызов функции в случае классов выполняется похож на обычный вызов функции, за исключением одной небольшой разницы. Аргументы помещаются в стек в обоих случаях, но в случае вызова функции объекта this помещается в стек в качестве первого аргумента. Это 'this' используется внутри функции для доступа к переменным-членам. Поскольку вы не обращаетесь ни к каким переменным-членам, он работает. И да, это может работать, даже если вы обращаетесь к переменным-членам, но вы получите неожиданное поведение, потому что компилятор может использовать память, выделенную для p. Как только компилятор использует эту память, вы начнете получать сбои. Например,
Я думаю, это зависит от среды (платформы / компилятора) ...
По крайней мере, это дает неожиданное поведение.
Думаю, вам повезло, что в вашем случае он не вылетает; -)