Enviado em 03/07/2021 - 10:58h
Já analisei o código abaixo com o valgrind (na verdade não sei utilizar isso ainda direito), mas ainda não entendi qual erro de alocação específico que está levando ao programa dar segmentation fault em tempo de execução.
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/times.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXCONN 3
#define SNDTIMEO 5
union sockaddr_any{
struct sockaddr generic;
struct sockaddr_in in;
struct sockaddr_in6 in6;
struct sockaddr_un un;
};
static bool set_sock_opts(int sockfd, size_t sndtimeo, bool only_ipv6) {
const int optval = 1;
struct timeval tm = {sndtimeo, 0};
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0 ) {
return false;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tm, sizeof(tm)) < 0 ) {
return false;
}
if (only_ipv6 == true) {
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)) < 0 ) {
return false;
}
}
return true;
}
static int make_server_socket(int addr_family, const char *service, bool only_ipv6, size_t sndtimeo, size_t somaxconn) {
int sockfd, errcode;
struct addrinfo hints, *result = NULL, *rp = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = addr_family;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
if ((errcode = getaddrinfo(NULL, service, &hints, &result)) < 0 ) {
fprintf(stderr, "make_server_socket() -> getaddrinfo() -> ERROR: %s\n", gai_strerror(errcode));
exit(EXIT_FAILURE);
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
if ((sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0 ) {
continue;
}
if ((set_sock_opts(sockfd, sndtimeo, only_ipv6)) != true ) {
close(sockfd);
continue;
}
if ((bind(sockfd, rp->ai_addr, rp->ai_addrlen)) == 0 ) {
break;
}
close(sockfd);
}
if (!rp) {
fprintf(stderr, "make_server_socket() -> socket()/bind() -> ERROR: %s\n", strerror(errno));
freeaddrinfo(result);
exit(EXIT_FAILURE);
}
freeaddrinfo(result);
if (listen(sockfd, somaxconn) < 0 ) {
fprintf(stderr, "make_server_socket() -> listen() -> ERROR: %s\n", strerror(errno));
close(sockfd);
exit(EXIT_FAILURE);
}
return sockfd;
}
static bool check_addr(int addr_family, const union sockaddr_any *addr, void **cache, size_t cache_size) {
if (addr_family == AF_UNIX) {
for (size_t i = 0; i < cache_size; i++) {
struct sockaddr_un *tmp = cache[i];
if (memcmp(addr->un.sun_path, tmp->sun_path, sizeof(tmp->sun_path)) == 0 ) {
return true;
}
}
} else if (addr_family == AF_INET) {
for (size_t i = 0; i < cache_size; i++) {
struct sockaddr_in *tmp = cache[i];
if (memcmp(&addr->in.sin_addr.s_addr, &tmp->sin_addr.s_addr, sizeof(tmp->sin_addr.s_addr)) == 0 ) {
return true;
}
}
} else if (addr_family == AF_INET6) {
for (size_t i = 0; i < cache_size; i++) {
struct sockaddr_in6 *tmp = cache[i];
if (memcmp(&addr->in6.sin6_addr.s6_addr, &tmp->sin6_addr.s6_addr, sizeof(tmp->sin6_addr.s6_addr)) == 0 ) {
return true;
}
}
} else {
for (size_t i = 0; i < cache_size; i++) {
struct sockaddr *tmp = cache[i];
if (memcmp(&addr->generic.sa_data, &tmp->sa_data, sizeof(tmp->sa_data)) == 0 ) {
return true;
}
}
}
return false;
}
static void show_addr(int addr_family, union sockaddr_any addr) {
char buff[INET6_ADDRSTRLEN];
if (addr_family == AF_UNIX) {
printf("%s\n", addr.un.sun_path);
} else if (addr_family == AF_INET) {
if (inet_ntop(addr_family, &addr.in.sin_addr.s_addr, buff, sizeof(buff)) < 0 ) {
fprintf(stderr, "show_addr() -> inet_ntop() -> ERROR: %s\n", strerror(errno));
} else {
printf("%s\n", buff);
}
} else if (addr_family == AF_INET6) {
if (inet_ntop(addr_family, &addr.in6.sin6_addr.s6_addr, buff, sizeof(buff)) < 0 ) {
fprintf(stderr, "show_addr() -> inet_ntop() -> ERROR: %s\n", strerror(errno));
} else {
printf("%s\n", buff);
}
} else {
fprintf(stderr, "show_addr() -> ERROR: Unexpected socket type\n");
}
}
static bool add_new_table_addr(void **cache, size_t *cache_size, int addr_family, union sockaddr_any *addr) {
socklen_t addrlen;
switch(addr_family) {
case AF_UNIX:
addrlen = sizeof(addr->un);
break;
case AF_INET:
addrlen = sizeof(addr->in);
break;
case AF_INET6:
addrlen = sizeof(addr->in6);
break;
default:
addrlen = sizeof(addr->generic);
}
void *new_addr = malloc(addrlen);
if (!new_addr) {
fprintf(stderr, "ERROR: Memory allocation for %u bytes failed\nadd_new_table_addr() -> malloc() -> ERROR: %s",
addrlen, strerror(errno));
return false;
}
void **new_ptr = realloc(cache, (1 + *cache_size) * sizeof(*cache));
if (!new_ptr) {
fprintf(stderr, "ERROR: Memory allocation for %zu bytes failed\nadd_new_table_addr() -> malloc() -> ERROR: %s",
(1 + *cache_size) * sizeof(*cache), strerror(errno));
free(new_addr);
return false;
}
memcpy(new_addr, addr, addrlen);
cache = new_ptr;
cache[*cache_size] = new_addr;
++*cache_size;
return true;
}
static void free_table(void **cache, size_t cache_size) {
for (size_t i = 0; i < cache_size; i++) {
free(cache[i]);
}
free(cache);
}
static void search(char *argv[], size_t somaxconn, size_t sndtimeo, size_t maxconn) {
int addr_family;
bool only_ipv6 = false;
if (strcmp(argv[1], "-u") == 0 ) {
addr_family = AF_UNIX;
} else if (strcmp(argv[1], "-4") == 0 ) {
addr_family = AF_INET;
} else if (strcmp(argv[1], "-6") == 0 ) {
addr_family = AF_INET6;
only_ipv6 = true;
} else {
addr_family = AF_INET6;
}
int sockfd = make_server_socket(addr_family, argv[2], only_ipv6, sndtimeo, somaxconn);
size_t cache_size = 0;
void **cache = NULL;
char err_msg[] = "Internal server error!", msg_1[] = "Welcome!", msg_2[] = "Get out!";
while (cache_size != maxconn) {
union sockaddr_any client_addr;
socklen_t addrlen = sizeof(client_addr);
int cli_sockfd = accept(sockfd, &client_addr.generic, &addrlen);
if (cli_sockfd < 0 ) {
fprintf(stderr, "search() -> accept() -> ERROR: %s\n", strerror(errno));
} else {
if (check_addr(addr_family, &client_addr, cache, cache_size) != true ) {
if (add_new_table_addr(cache, &cache_size, addr_family, &client_addr) != true ) {
if (send(cli_sockfd, err_msg, sizeof(err_msg), 0) < 0 ) {
fprintf(stderr, "search() -> send() -> ERROR: %s\n", strerror(errno));
}
} else {
show_addr(addr_family, client_addr);
if (send(cli_sockfd, msg_1, sizeof(msg_1), 0) < 0 ) {
fprintf(stderr, "search() -> send() -> ERROR: %s\n", strerror(errno));
}
}
} else {
if (send(cli_sockfd, msg_2, sizeof(msg_2), 0) < 0 ) {
fprintf(stderr, "search() -> send() -> ERROR: %s\n", strerror(errno));
}
}
close(cli_sockfd);
}
}
close(sockfd);
free_table(cache, cache_size);
}
int main(int argc, char *argv[]) {
if (argc == 1) {
printf(" *** ERROR: No arguments! ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [SNDTIMEO] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
exit(EXIT_FAILURE);
}
int opt = getopt(argc, argv, "u46Mh");
if (strlen(argv[1]) > 2 ) {
printf("*** Invalid value for [OPTION] ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [SNDTIMEO] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
} else if (opt == 'h' || opt == '?') {
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [SNDTIMEO] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
} else if ((argc > 6) || (argc < 6)) {
printf("*** Invalid arguments! ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [SNDTIMEO] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
} else {
size_t somaxconn = strtoull(argv[3], NULL, 10);
size_t sndtimeo = strtoull(argv[4], NULL, 10);
size_t maxconn = strtoull(argv[5], NULL, 10);
if (somaxconn > SOMAXCONN) {
printf("*** ERROR: The value passed for [SOMAXCONN] is too long! ***\n");
printf("The maximum allowed value is %d\n", SOMAXCONN);
} else if (sndtimeo > SNDTIMEO) {
printf("*** ERROR: The value passed for [SNDTIMEO] is too long! ***\n");
printf("The maximum allowed value is %d\n", SNDTIMEO);
} else if (maxconn > MAXCONN) {
printf("*** ERROR: The value passed for [MAXCONN] is too long! ***\n");
printf("The maximum allowed value is %d\n", MAXCONN);
} else {
search(argv, somaxconn, sndtimeo, maxconn);
}
}
return EXIT_SUCCESS;
}
$ valgrind --leak-check=full ./server -M 9009 4096 5 3
==10626== Memcheck, a memory error detector
==10626== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10626== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==10626== Command: ./server -M 9009 4096 5 3
==10626==
::1
==10626== Invalid read of size 8
==10626== at 0x1098ED: check_addr (in /home/xubuntu/Documents/server)
==10626== by 0x109E2E: search (in /home/xubuntu/Documents/server)
==10626== by 0x10A2FA: main (in /home/xubuntu/Documents/server)
==10626== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==10626==
==10626==
==10626== Process terminating with default action of signal 11 (SIGSEGV)
==10626== Access not within mapped region at address 0x0
==10626== at 0x1098ED: check_addr (in /home/xubuntu/Documents/server)
==10626== by 0x109E2E: search (in /home/xubuntu/Documents/server)
==10626== by 0x10A2FA: main (in /home/xubuntu/Documents/server)
==10626== If you believe this happened as a result of a stack
==10626== overflow in your program's main thread (unlikely but
==10626== possible), you can try to increase the size of the
==10626== main thread stack using the --main-stacksize= flag.
==10626== The main thread stack size used in this run was 8388608.
==10626==
==10626== HEAP SUMMARY:
==10626== in use at exit: 36 bytes in 2 blocks
==10626== total heap usage: 4 allocs, 2 frees, 1,136 bytes allocated
==10626==
==10626== 36 (8 direct, 28 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==10626== at 0x483B723: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10626== by 0x483E017: realloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10626== by 0x109B1B: add_new_table_addr (in /home/xubuntu/Documents/server)
==10626== by 0x109E5C: search (in /home/xubuntu/Documents/server)
==10626== by 0x10A2FA: main (in /home/xubuntu/Documents/server)
==10626==
==10626== LEAK SUMMARY:
==10626== definitely lost: 8 bytes in 1 blocks
==10626== indirectly lost: 28 bytes in 1 blocks
==10626== possibly lost: 0 bytes in 0 blocks
==10626== still reachable: 0 bytes in 0 blocks
==10626== suppressed: 0 bytes in 0 blocks
==10626==
==10626== For lists of detected and suppressed errors, rerun with: -s
==10626== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define SNDTIMEO 5
#define MAXCONN 10
static bool set_sock_opts(int sockfd, bool only_ipv6) {
bool ok = false;
const int optval = 1;
struct timeval timeout = {SNDTIMEO, 0};
do {
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != 0 ) {
break;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) != 0 ) {
break;
}
if (only_ipv6 == true) {
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)) != 0 ) {
break;
}
}
ok = true;
} while (false);
return ok;
}
static int make_server_socket(int af, const char *service, bool only_ipv6, size_t somaxconn) {
int sockfd, ecode;
struct addrinfo hints, *result = NULL, *rp = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = af;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
if ((ecode = getaddrinfo(NULL, service, &hints, &result)) != 0 ) {
fprintf(stderr, "make_server_socket() -> getaddrinfo() -> ERROR: %s\n", gai_strerror(ecode));
exit(EXIT_FAILURE);
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
if ((sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0 ) {
continue;
}
if (set_sock_opts(sockfd, only_ipv6) != true ) {
close(sockfd);
continue;
}
if (bind(sockfd, rp->ai_addr, rp->ai_addrlen) != -1 ) {
break;
}
close(sockfd);
}
if (rp == NULL) {
fprintf(stderr, "make_server_socket() -> socket()/bind() -> ERROR: %s\n", strerror(errno));
freeaddrinfo(rp);
exit(EXIT_FAILURE);
}
freeaddrinfo(rp);
if (listen(sockfd, somaxconn) < 0 ) {
fprintf(stderr, "make_server_socket() -> listen() -> ERROR: %s\n", strerror(errno));
close(sockfd);
exit(EXIT_FAILURE);
}
return sockfd;
}
static bool check_addr(int af, void *addr, void **addr_table, size_t count) {
bool found = false;
if (af == AF_UNIX) {
struct sockaddr_un *un = addr;
for (size_t i = 0; i < count; i++) {
struct sockaddr_un *tmp = addr_table[i];
if (memcmp(un->sun_path, tmp->sun_path, sizeof(un->sun_path)) == 0 ) {
found = true;
break;
}
}
} else if (af == AF_INET) {
struct sockaddr_in *in = addr;
for (size_t i = 0; i < count; i++) {
struct sockaddr_in *tmp = addr_table[i];
if (memcmp(&in->sin_addr.s_addr, &tmp->sin_addr.s_addr, sizeof(in->sin_addr.s_addr)) == 0 ) {
found = true;
break;
}
}
} else {
struct sockaddr_in6 *in6 = addr;
for(size_t i = 0; i < count; i++) {
struct sockaddr_in6 *tmp = addr_table[i];
if (memcmp(&in6->sin6_addr.s6_addr, &tmp->sin6_addr.s6_addr, sizeof(in6->sin6_addr.s6_addr)) == 0 ) {
found = true;
break;
}
}
}
return found;
}
static void show_addr(int af, void *addr) {
char buff[INET6_ADDRSTRLEN];
if (af == AF_UNIX) {
struct sockaddr_un *un = addr;
printf("%s\n", un->sun_path);
} else if (af == AF_INET) {
struct sockaddr_in *in = addr;
if (inet_ntop(af, &in->sin_addr.s_addr, buff, INET_ADDRSTRLEN) < 0 ) {
fprintf(stderr, "show_addr() -> inet_ntop() -> ERROR: %s\n", strerror(errno));
} else {
printf("%s\n", buff);
}
} else {
struct sockaddr_in6 *in6 = addr;
if (inet_ntop(af, &in6->sin6_addr.s6_addr, buff, INET6_ADDRSTRLEN) < 0 ) {
fprintf(stderr, "show_addr() -> inet_ntop() -> ERROR: %s\n", strerror(errno));
} else {
printf("%s\n", buff);
}
}
}
static void **realloc_addr_table(void **addr_table, size_t count, socklen_t addrlen) {
void **tmp = realloc(addr_table, count * sizeof(*addr_table));
if (tmp == NULL) {
fprintf(stderr, "ERROR: Memory allocation for %zu bytes failed\nrealloc_addr_table() -> realloc() -> ERROR: %s\n",
count * sizeof(*addr_table), strerror(errno));
} else {
tmp[count-1] = malloc(addrlen);
if (tmp == NULL) {
fprintf(stderr, "ERROR: Memory allocation for %u bytes failed\nrealloc_addr_table -> realloc() -> ERROR: %s\n",
addrlen, strerror(errno));
}
}
return tmp;
}
static void free_addr_table(void **addr_table, size_t count) {
for (size_t i = 0; i < count; i++) {
free(addr_table[i]);
}
free(addr_table);
}
static void search(char **argv, size_t somaxconn, size_t maxconn) {
int af;
bool only_ipv6 = false;
socklen_t addrlen;
if (strcmp(argv[1], "-u") == 0 ) {
af = AF_UNIX;
addrlen = sizeof(struct sockaddr_un);
} else if (strcmp(argv[1], "-4") == 0 ) {
af = AF_INET;
addrlen = sizeof(struct sockaddr_in);
} else if (strcmp(argv[1], "-6") == 0 ) {
af = AF_INET6;
only_ipv6 = true;
addrlen = sizeof(struct sockaddr_in6);
} else {
af = AF_INET6;
addrlen = sizeof(struct sockaddr_in6);
}
size_t i = 0;
int sockfd = make_server_socket(af, argv[2], only_ipv6, somaxconn);
void *addr = malloc(addrlen);
void **addr_table = NULL;
const char msg_1[] = "Welcome!\n", err_msg[] = "Internal server error!", msg_2[] = "Get out!\n";
while (i < maxconn) {
int cli_sockfd;
if ((cli_sockfd = accept(sockfd, addr, &addrlen)) < 0 ) {
fprintf(stderr, "search() -> accept() -> ERROR: %s\n", strerror(errno));
} else {
if (check_addr(af, addr, addr_table, i) == false ) {
void **tmp = realloc_addr_table(addr_table, i+1, addrlen);
if (!tmp) {
send(cli_sockfd, err_msg, sizeof(err_msg), 0);
} else {
i++;
addr_table = tmp;
memcpy(addr_table[i-1], addr, addrlen);
show_addr(af, addr);
send(cli_sockfd, msg_1, sizeof(msg_1), 0);
}
}else{
send(cli_sockfd, msg_2, sizeof(msg_2), 0);
}
close(cli_sockfd);
}
}
free(addr);
free_addr_table(addr_table, i);
close(sockfd);
}
int main(int argc, char **argv) {
if (argc == 1) {
printf(" *** ERROR: No arguments! ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
exit(EXIT_FAILURE);
}
int opt = getopt(argc, argv, "u46Mh");
if (strlen(argv[1]) > 2 ) {
printf("*** Invalid value for [OPTION]! ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
} else if (opt == 'h' || opt == '?') {
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
} else if ((argc < 5) || (argc > 5)) {
printf("*** Invalid arguments! ***\n");
printf("Usage: %s [OPTION] [PORT/SERVICE] [SOMAXCONN] [MAXCONN]\n", argv[0]);
printf(" -u Use process comunication\n");
printf(" -4 Use IPv4\n");
printf(" -6 Use IPv6\n");
printf(" -M Use IPv4 and IPv6 (IPv4-Mapped IPv6 Adress)\n");
printf(" -h Show this page\n");
} else {
size_t somaxconn = strtoull(argv[3], NULL, 10);
size_t maxconn = strtoull(argv[4], NULL, 10);
if (somaxconn > SOMAXCONN) {
printf("*** ERROR: The value passed for [SOMAXCONN] is too long! ***\n");
printf("The maximum allowed value is %d\n", SOMAXCONN);
} else if (maxconn > MAXCONN) {
printf("*** ERROR: The value passed for [MAXCONN] is too long! ***\n");
printf("The maximum allowed value is %d\n", MAXCONN);
} else {
search(argv, somaxconn, maxconn);
}
}
return EXIT_SUCCESS;
}
$ gcc -Wall server_1.c -o server
$ valgrind --leak-check=full ./server -M 9009 4096 3
==6549== Memcheck, a memory error detector
==6549== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6549== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==6549== Command: ./server -M 9009 4096 3
==6549==
::ffff:127.0.0.1
::1
::ffff:192.168.50.2
==6549==
==6549== HEAP SUMMARY:
==6549== in use at exit: 0 bytes in 0 blocks
==6549== total heap usage: 9 allocs, 9 frees, 1,260 bytes allocated
==6549==
==6549== All heap blocks were freed -- no leaks are possible
==6549==
==6549== For lists of detected and suppressed errors, rerun with: -s
==6549== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Como renomear arquivos de letras maiúsculas para minúsculas
Imprimindo no formato livreto no Linux
Vim - incrementando números em substituição
Efeito "livro" em arquivos PDF
Como resolver o erro no CUPS: Unable to get list of printer drivers
Notebook Novo. Aceita Duplo Boot? (2)
Não estou conseguindo habilitar os timezones (1)
verificar se uma fonte já esta instalada (30)
[Python] Automação de scan de vulnerabilidades
[Python] Script para analise de superficie de ataque
[Shell Script] Novo script para redimensionar, rotacionar, converter e espelhar arquivos de imagem
[Shell Script] Iniciador de DOOM (DSDA-DOOM, Doom Retro ou Woof!)
[Shell Script] Script para adicionar bordas às imagens de uma pasta